From d652cb8525caa9be2536f56bd942564073df0f3a Mon Sep 17 00:00:00 2001 From: heck Date: Tue, 5 Sep 2023 15:08:37 +0200 Subject: [PATCH] Use original STM32 HAL DRIVER --- Makefile | 8 +- .../Inc}/Legacy/stm32_hal_legacy.h | 2 +- .../Inc/Legacy/stm32f4xx_hal_can_legacy.h | 765 ++ .../Inc/Legacy/stm32f4xx_hal_eth_legacy.h | 2209 +++ .../Inc/stm32_assert_template.h | 56 + .../Inc}/stm32f4xx_hal.h | 0 .../Inc/stm32f4xx_hal_adc.h | 898 ++ .../Inc/stm32f4xx_hal_adc_ex.h | 407 + .../Inc/stm32f4xx_hal_can.h | 853 ++ .../Inc/stm32f4xx_hal_cec.h | 792 ++ .../Inc/stm32f4xx_hal_conf.h | 500 + .../Inc/stm32f4xx_hal_conf_template.h} | 233 +- .../Inc}/stm32f4xx_hal_cortex.h | 0 .../Inc/stm32f4xx_hal_crc.h | 181 + .../Inc/stm32f4xx_hal_cryp.h | 683 + .../Inc/stm32f4xx_hal_cryp_ex.h | 142 + .../Inc}/stm32f4xx_hal_dac.h | 0 .../Inc}/stm32f4xx_hal_dac_ex.h | 0 .../Inc/stm32f4xx_hal_dcmi.h | 563 + .../Inc/stm32f4xx_hal_dcmi_ex.h | 208 + .../Inc}/stm32f4xx_hal_def.h | 2 + .../Inc/stm32f4xx_hal_dfsdm.h | 1141 ++ .../Inc}/stm32f4xx_hal_dma.h | 0 .../Inc/stm32f4xx_hal_dma2d.h | 638 + .../Inc}/stm32f4xx_hal_dma_ex.h | 0 .../Inc/stm32f4xx_hal_dsi.h | 1377 ++ .../Inc/stm32f4xx_hal_eth.h | 2144 +++ .../Inc}/stm32f4xx_hal_exti.h | 0 .../Inc}/stm32f4xx_hal_flash.h | 0 .../Inc}/stm32f4xx_hal_flash_ex.h | 0 .../Inc}/stm32f4xx_hal_flash_ramfunc.h | 0 .../Inc/stm32f4xx_hal_fmpi2c.h | 841 ++ .../Inc/stm32f4xx_hal_fmpi2c_ex.h | 150 + .../Inc/stm32f4xx_hal_fmpsmbus.h | 793 ++ .../Inc/stm32f4xx_hal_fmpsmbus_ex.h | 136 + .../Inc}/stm32f4xx_hal_gpio.h | 0 .../Inc}/stm32f4xx_hal_gpio_ex.h | 0 .../Inc/stm32f4xx_hal_hash.h | 634 + .../Inc/stm32f4xx_hal_hash_ex.h | 175 + .../Inc/stm32f4xx_hal_hcd.h | 316 + .../Inc/stm32f4xx_hal_i2c.h | 741 + .../Inc/stm32f4xx_hal_i2c_ex.h | 115 + .../Inc/stm32f4xx_hal_i2s.h | 618 + .../Inc/stm32f4xx_hal_i2s_ex.h | 183 + .../Inc/stm32f4xx_hal_irda.h | 682 + .../Inc/stm32f4xx_hal_iwdg.h | 220 + .../Inc/stm32f4xx_hal_lptim.h | 857 ++ .../Inc/stm32f4xx_hal_ltdc.h | 719 + .../Inc/stm32f4xx_hal_ltdc_ex.h | 83 + .../Inc/stm32f4xx_hal_mmc.h | 747 + .../Inc/stm32f4xx_hal_nand.h | 388 + .../Inc/stm32f4xx_hal_nor.h | 330 + .../Inc/stm32f4xx_hal_pccard.h | 285 + .../Inc}/stm32f4xx_hal_pcd.h | 0 .../Inc}/stm32f4xx_hal_pcd_ex.h | 0 .../Inc}/stm32f4xx_hal_pwr.h | 0 .../Inc}/stm32f4xx_hal_pwr_ex.h | 0 .../Inc/stm32f4xx_hal_qspi.h | 750 + .../Inc}/stm32f4xx_hal_rcc.h | 2 +- .../Inc}/stm32f4xx_hal_rcc_ex.h | 4 +- .../Inc}/stm32f4xx_hal_rng.h | 0 .../Inc/stm32f4xx_hal_rtc.h | 922 ++ .../Inc/stm32f4xx_hal_rtc_ex.h | 1079 ++ .../Inc/stm32f4xx_hal_sai.h | 895 ++ .../Inc/stm32f4xx_hal_sai_ex.h | 114 + .../Inc/stm32f4xx_hal_sd.h | 758 + .../Inc/stm32f4xx_hal_sdram.h | 238 + .../Inc/stm32f4xx_hal_smartcard.h | 755 + .../Inc/stm32f4xx_hal_smbus.h | 731 + .../Inc/stm32f4xx_hal_spdifrx.h | 604 + .../Inc/stm32f4xx_hal_spi.h | 729 + .../Inc/stm32f4xx_hal_sram.h | 236 + .../Inc}/stm32f4xx_hal_tim.h | 54 +- .../Inc}/stm32f4xx_hal_tim_ex.h | 19 +- .../Inc/stm32f4xx_hal_uart.h | 909 ++ .../Inc/stm32f4xx_hal_usart.h | 648 + .../Inc/stm32f4xx_hal_wwdg.h | 298 + .../Inc/stm32f4xx_ll_adc.h | 4782 +++++++ .../Inc}/stm32f4xx_ll_bus.h | 0 .../Inc}/stm32f4xx_ll_cortex.h | 0 .../Inc/stm32f4xx_ll_crc.h | 201 + .../Inc}/stm32f4xx_ll_dac.h | 0 .../Inc}/stm32f4xx_ll_dma.h | 0 .../Inc/stm32f4xx_ll_dma2d.h | 1901 +++ .../Inc}/stm32f4xx_ll_exti.h | 0 .../Inc/stm32f4xx_ll_fmc.h | 1416 ++ .../Inc/stm32f4xx_ll_fmpi2c.h | 2234 +++ .../Inc/stm32f4xx_ll_fsmc.h | 1086 ++ .../Inc}/stm32f4xx_ll_gpio.h | 0 .../Inc/stm32f4xx_ll_i2c.h | 1890 +++ .../Inc/stm32f4xx_ll_iwdg.h | 302 + .../Inc/stm32f4xx_ll_lptim.h | 1378 ++ .../Inc}/stm32f4xx_ll_pwr.h | 0 .../Inc}/stm32f4xx_ll_rcc.h | 0 .../Inc}/stm32f4xx_ll_rng.h | 0 .../Inc/stm32f4xx_ll_rtc.h | 3663 +++++ .../Inc/stm32f4xx_ll_sdmmc.h | 1141 ++ .../Inc/stm32f4xx_ll_spi.h | 2027 +++ .../Inc}/stm32f4xx_ll_system.h | 0 .../Inc}/stm32f4xx_ll_tim.h | 130 +- .../Inc/stm32f4xx_ll_usart.h | 2521 ++++ .../Inc}/stm32f4xx_ll_usb.h | 0 .../Inc}/stm32f4xx_ll_utils.h | 0 .../Inc/stm32f4xx_ll_wwdg.h | 316 + libs/STM32F4xx_HAL_Driver/LICENSE.md | 27 + libs/STM32F4xx_HAL_Driver/README.md | 38 + libs/STM32F4xx_HAL_Driver/Release_Notes.html | 11459 ++++++++++++++++ .../Src/Legacy/stm32f4xx_hal_can.c | 1679 +++ .../Src/Legacy/stm32f4xx_hal_eth.c | 2307 ++++ libs/STM32F4xx_HAL_Driver/Src/Makefile | 28 + .../Src}/stm32f4xx_hal.c | 0 .../Src/stm32f4xx_hal_adc.c | 2110 +++ .../Src/stm32f4xx_hal_adc_ex.c | 1112 ++ .../Src/stm32f4xx_hal_can.c | 2466 ++++ .../Src/stm32f4xx_hal_cec.c | 996 ++ .../Src}/stm32f4xx_hal_cortex.c | 0 .../Src/stm32f4xx_hal_crc.c | 328 + .../Src/stm32f4xx_hal_cryp.c | 7158 ++++++++++ .../Src/stm32f4xx_hal_cryp_ex.c | 680 + .../Src}/stm32f4xx_hal_dac.c | 0 .../Src}/stm32f4xx_hal_dac_ex.c | 0 .../Src/stm32f4xx_hal_dcmi.c | 1161 ++ .../Src/stm32f4xx_hal_dcmi_ex.c | 182 + .../Src/stm32f4xx_hal_dfsdm.c | 4423 ++++++ .../Src}/stm32f4xx_hal_dma.c | 0 .../Src/stm32f4xx_hal_dma2d.c | 2126 +++ .../Src}/stm32f4xx_hal_dma_ex.c | 0 .../Src/stm32f4xx_hal_dsi.c | 3117 +++++ .../Src/stm32f4xx_hal_eth.c | 3220 +++++ .../Src}/stm32f4xx_hal_exti.c | 4 +- .../Src}/stm32f4xx_hal_flash.c | 0 .../Src}/stm32f4xx_hal_flash_ex.c | 0 .../Src}/stm32f4xx_hal_flash_ramfunc.c | 0 .../Src/stm32f4xx_hal_fmpi2c.c | 7322 ++++++++++ .../Src/stm32f4xx_hal_fmpi2c_ex.c | 258 + .../Src/stm32f4xx_hal_fmpsmbus.c | 2808 ++++ .../Src/stm32f4xx_hal_fmpsmbus_ex.c | 145 + .../Src}/stm32f4xx_hal_gpio.c | 0 .../Src/stm32f4xx_hal_hash.c | 3514 +++++ .../Src/stm32f4xx_hal_hash_ex.c | 1040 ++ .../Src/stm32f4xx_hal_hcd.c | 1728 +++ .../Src/stm32f4xx_hal_i2c.c | 7534 ++++++++++ .../Src/stm32f4xx_hal_i2c_ex.c | 182 + .../Src/stm32f4xx_hal_i2s.c | 2094 +++ .../Src/stm32f4xx_hal_i2s_ex.c | 1135 ++ .../Src/stm32f4xx_hal_irda.c | 2687 ++++ .../Src/stm32f4xx_hal_iwdg.c | 262 + .../Src/stm32f4xx_hal_lptim.c | 2484 ++++ .../Src/stm32f4xx_hal_ltdc.c | 2215 +++ .../Src/stm32f4xx_hal_ltdc_ex.c | 151 + .../Src/stm32f4xx_hal_mmc.c | 3201 +++++ .../Src/stm32f4xx_hal_msp_template.c | 100 + .../Src/stm32f4xx_hal_nand.c | 2405 ++++ .../Src/stm32f4xx_hal_nor.c | 1543 +++ .../Src/stm32f4xx_hal_pccard.c | 946 ++ .../Src}/stm32f4xx_hal_pcd.c | 0 .../Src}/stm32f4xx_hal_pcd_ex.c | 0 .../Src}/stm32f4xx_hal_pwr.c | 3 + .../Src}/stm32f4xx_hal_pwr_ex.c | 0 .../Src/stm32f4xx_hal_qspi.c | 2915 ++++ .../Src}/stm32f4xx_hal_rcc.c | 4 +- .../Src}/stm32f4xx_hal_rcc_ex.c | 0 .../Src}/stm32f4xx_hal_rng.c | 0 .../Src/stm32f4xx_hal_rtc.c | 1908 +++ .../Src/stm32f4xx_hal_rtc_ex.c | 1878 +++ .../Src/stm32f4xx_hal_sai.c | 2554 ++++ .../Src/stm32f4xx_hal_sai_ex.c | 310 + .../Src/stm32f4xx_hal_sd.c | 3277 +++++ .../Src/stm32f4xx_hal_sdram.c | 1308 ++ .../Src/stm32f4xx_hal_smartcard.c | 2364 ++++ .../Src/stm32f4xx_hal_smbus.c | 2804 ++++ .../Src/stm32f4xx_hal_spdifrx.c | 1627 +++ .../Src/stm32f4xx_hal_spi.c | 3935 ++++++ .../Src/stm32f4xx_hal_sram.c | 1110 ++ .../Src}/stm32f4xx_hal_tim.c | 66 +- .../Src}/stm32f4xx_hal_tim_ex.c | 16 +- ...tm32f4xx_hal_timebase_rtc_alarm_template.c | 318 + ...m32f4xx_hal_timebase_rtc_wakeup_template.c | 293 + .../Src/stm32f4xx_hal_timebase_tim_template.c | 177 + .../Src/stm32f4xx_hal_uart.c | 3759 +++++ .../Src/stm32f4xx_hal_usart.c | 2838 ++++ .../Src/stm32f4xx_hal_wwdg.c | 420 + .../Src/stm32f4xx_ll_adc.c | 922 ++ .../Src/stm32f4xx_ll_crc.c | 103 + .../Src/stm32f4xx_ll_dac.c | 280 + .../Src/stm32f4xx_ll_dma.c | 423 + .../Src/stm32f4xx_ll_dma2d.c | 594 + .../Src/stm32f4xx_ll_exti.c | 212 + .../Src/stm32f4xx_ll_fmc.c | 1498 ++ .../Src/stm32f4xx_ll_fmpi2c.c | 217 + .../Src/stm32f4xx_ll_fsmc.c | 1062 ++ .../Src/stm32f4xx_ll_gpio.c | 303 + .../Src/stm32f4xx_ll_i2c.c | 251 + .../Src/stm32f4xx_ll_lptim.c | 301 + .../Src/stm32f4xx_ll_pwr.c | 81 + .../Src/stm32f4xx_ll_rcc.c | 1660 +++ .../Src/stm32f4xx_ll_rng.c | 111 + .../Src/stm32f4xx_ll_rtc.c | 838 ++ .../Src/stm32f4xx_ll_sdmmc.c | 1578 +++ .../Src/stm32f4xx_ll_spi.c | 624 + .../Src/stm32f4xx_ll_tim.c | 1189 ++ .../Src/stm32f4xx_ll_usart.c | 500 + .../Src}/stm32f4xx_ll_usb.c | 5 +- .../Src/stm32f4xx_ll_utils.c | 749 + .../STM32F4xx_HAL_Driver/_htmresc/mini-st.css | 1700 +++ .../STM32F4xx_HAL_Driver/_htmresc/st_logo.png | Bin 0 -> 18616 bytes libs/hal/Makefile | 26 - libs/st_usb/Makefile | 13 +- src/Makefile | 12 +- 209 files changed, 194755 insertions(+), 304 deletions(-) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/Legacy/stm32_hal_legacy.h (99%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_eth_legacy.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf.h rename libs/{hal/stm32f4xx_hal_conf.h => STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h} (70%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_cortex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_dac.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_dac_ex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_def.h (99%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_dma.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_dma_ex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_exti.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_flash.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_flash_ex.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_flash_ramfunc.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus_ex.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_gpio.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_gpio_ex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_pcd.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_pcd_ex.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_pwr.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_pwr_ex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_rcc.h (99%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_rcc_ex.h (99%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_rng.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_tim.h (98%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_hal_tim_ex.h (96%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_bus.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_cortex.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_dac.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_dma.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_exti.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_gpio.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_pwr.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_rcc.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_rng.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_system.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_tim.h (97%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_usb.h (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Inc}/stm32f4xx_ll_utils.h (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h create mode 100644 libs/STM32F4xx_HAL_Driver/LICENSE.md create mode 100644 libs/STM32F4xx_HAL_Driver/README.md create mode 100644 libs/STM32F4xx_HAL_Driver/Release_Notes.html create mode 100644 libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_eth.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/Makefile rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_cortex.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_dac.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_dac_ex.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_dma.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_dma_ex.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_exti.c (98%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_flash.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_flash_ex.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_flash_ramfunc.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus_ex.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_gpio.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_pcd.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_pcd_ex.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_pwr.c (99%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_pwr_ex.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_rcc.c (99%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_rcc_ex.c (100%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_rng.c (100%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_tim.c (99%) rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_hal_tim_ex.c (99%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c rename libs/{hal => STM32F4xx_HAL_Driver/Src}/stm32f4xx_ll_usb.c (99%) create mode 100644 libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c create mode 100644 libs/STM32F4xx_HAL_Driver/_htmresc/mini-st.css create mode 100644 libs/STM32F4xx_HAL_Driver/_htmresc/st_logo.png delete mode 100644 libs/hal/Makefile diff --git a/Makefile b/Makefile index 502a12a..12d7078 100644 --- a/Makefile +++ b/Makefile @@ -14,12 +14,14 @@ run: compile compile: $(MAKE) -C libs/cmsis - $(MAKE) -C libs/hal + $(MAKE) -C libs/STM32F4xx_HAL_Driver/Src $(MAKE) -C libs/st_usb $(MAKE) -C src clean: + $(MAKE) -C src clean + +clean-all: clean $(MAKE) -C libs/cmsis clean - $(MAKE) -C libs/hal clean + $(MAKE) -C libs/STM32F4xx_HAL_Driver/Src clean $(MAKE) -C libs/st_usb clean - $(MAKE) -C src clean diff --git a/libs/hal/Legacy/stm32_hal_legacy.h b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h similarity index 99% rename from libs/hal/Legacy/stm32_hal_legacy.h rename to libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h index 934f1f9..06cded9 100644 --- a/libs/hal/Legacy/stm32_hal_legacy.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32_hal_legacy.h @@ -1283,7 +1283,7 @@ extern "C" { #define TIM_TIM3_TI1_COMP1COMP2_OUT TIM_TIM3_TI1_COMP1_COMP2 #endif -#if defined(STM32U5) || defined(STM32MP2) +#if defined(STM32U5) #define OCREF_CLEAR_SELECT_Pos OCREF_CLEAR_SELECT_POS #define OCREF_CLEAR_SELECT_Msk OCREF_CLEAR_SELECT_MSK #endif diff --git a/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h new file mode 100644 index 0000000..e4d774b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_can_legacy.h @@ -0,0 +1,765 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_can_legacy.h + * @author MCD Application Team + * @brief Header file of CAN 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 __STM32F4xx_HAL_CAN_LEGACY_H +#define __STM32F4xx_HAL_CAN_LEGACY_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ + defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||\ + defined(STM32F423xx) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CAN + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CAN_Exported_Types CAN Exported Types + * @{ + */ + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_CAN_STATE_RESET = 0x00U, /*!< CAN not yet initialized or disabled */ + HAL_CAN_STATE_READY = 0x01U, /*!< CAN initialized and ready for use */ + HAL_CAN_STATE_BUSY = 0x02U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_TX = 0x12U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_RX0 = 0x22U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_RX1 = 0x32U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_TX_RX0 = 0x42U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_TX_RX1 = 0x52U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_RX0_RX1 = 0x62U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_BUSY_TX_RX0_RX1 = 0x72U, /*!< CAN process is ongoing */ + HAL_CAN_STATE_TIMEOUT = 0x03U, /*!< CAN in Timeout state */ + HAL_CAN_STATE_ERROR = 0x04U /*!< CAN error state */ + +}HAL_CAN_StateTypeDef; + +/** + * @brief CAN init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the length of a time quantum. + This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */ + + uint32_t Mode; /*!< Specifies the CAN operating mode. + This parameter can be a value of @ref CAN_operating_mode */ + + uint32_t SJW; /*!< Specifies the maximum number of time quanta + the CAN hardware is allowed to lengthen or + shorten a bit to perform resynchronization. + This parameter can be a value of @ref CAN_synchronisation_jump_width */ + + uint32_t BS1; /*!< Specifies the number of time quanta in Bit Segment 1. + This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */ + + uint32_t BS2; /*!< Specifies the number of time quanta in Bit Segment 2. + This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */ + + uint32_t TTCM; /*!< Enable or disable the time triggered communication mode. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t ABOM; /*!< Enable or disable the automatic bus-off management. + This parameter can be set to ENABLE or DISABLE */ + + uint32_t AWUM; /*!< Enable or disable the automatic wake-up mode. + This parameter can be set to ENABLE or DISABLE */ + + uint32_t NART; /*!< Enable or disable the non-automatic retransmission mode. + This parameter can be set to ENABLE or DISABLE */ + + uint32_t RFLM; /*!< Enable or disable the receive FIFO Locked mode. + This parameter can be set to ENABLE or DISABLE */ + + uint32_t TXFP; /*!< Enable or disable the transmit FIFO priority. + This parameter can be set to ENABLE or DISABLE */ +}CAN_InitTypeDef; + +/** + * @brief CAN filter configuration structure definition + */ +typedef struct +{ + uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t FilterMaskIdLow; /*!< Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */ + + uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint32_t FilterNumber; /*!< Specifies the filter which will be initialized. + This parameter must be a number between Min_Data = 0 and Max_Data = 27 */ + + uint32_t FilterMode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint32_t FilterScale; /*!< Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + uint32_t FilterActivation; /*!< Enable or disable the filter. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t BankNumber; /*!< Select the start slave bank filter. + This parameter must be a number between Min_Data = 0 and Max_Data = 28 */ + +}CAN_FilterConfTypeDef; + +/** + * @brief CAN Tx message structure definition + */ +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted. + This parameter can be a value of @ref CAN_Identifier_Type */ + + uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted. + This parameter can be a value of @ref CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted. + This parameter must be a number between Min_Data = 0 and Max_Data = 8 */ + + uint8_t Data[8]; /*!< Contains the data to be transmitted. + This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */ + +}CanTxMsgTypeDef; + +/** + * @brief CAN Rx message structure definition + */ +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will be received. + This parameter can be a value of @ref CAN_Identifier_Type */ + + uint32_t RTR; /*!< Specifies the type of frame for the received message. + This parameter can be a value of @ref CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be received. + This parameter must be a number between Min_Data = 0 and Max_Data = 8 */ + + uint8_t Data[8]; /*!< Contains the data to be received. + This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */ + + uint32_t FMI; /*!< Specifies the index of the filter the message stored in the mailbox passes through. + This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */ + + uint32_t FIFONumber; /*!< Specifies the receive FIFO number. + This parameter can be CAN_FIFO0 or CAN_FIFO1 */ + +}CanRxMsgTypeDef; + +/** + * @brief CAN handle Structure definition + */ +typedef struct +{ + CAN_TypeDef *Instance; /*!< Register base address */ + + CAN_InitTypeDef Init; /*!< CAN required parameters */ + + CanTxMsgTypeDef* pTxMsg; /*!< Pointer to transmit structure */ + + CanRxMsgTypeDef* pRxMsg; /*!< Pointer to reception structure for RX FIFO0 msg */ + + CanRxMsgTypeDef* pRx1Msg; /*!< Pointer to reception structure for RX FIFO1 msg */ + + __IO HAL_CAN_StateTypeDef State; /*!< CAN communication state */ + + HAL_LockTypeDef Lock; /*!< CAN locking object */ + + __IO uint32_t ErrorCode; /*!< CAN Error code */ + +}CAN_HandleTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CAN_Exported_Constants CAN Exported Constants + * @{ + */ + +/** @defgroup CAN_Error_Code CAN Error Code + * @{ + */ +#define HAL_CAN_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_CAN_ERROR_EWG 0x00000001U /*!< EWG error */ +#define HAL_CAN_ERROR_EPV 0x00000002U /*!< EPV error */ +#define HAL_CAN_ERROR_BOF 0x00000004U /*!< BOF error */ +#define HAL_CAN_ERROR_STF 0x00000008U /*!< Stuff error */ +#define HAL_CAN_ERROR_FOR 0x00000010U /*!< Form error */ +#define HAL_CAN_ERROR_ACK 0x00000020U /*!< Acknowledgment error */ +#define HAL_CAN_ERROR_BR 0x00000040U /*!< Bit recessive */ +#define HAL_CAN_ERROR_BD 0x00000080U /*!< LEC dominant */ +#define HAL_CAN_ERROR_CRC 0x00000100U /*!< LEC transfer error */ +#define HAL_CAN_ERROR_FOV0 0x00000200U /*!< FIFO0 overrun error */ +#define HAL_CAN_ERROR_FOV1 0x00000400U /*!< FIFO1 overrun error */ +#define HAL_CAN_ERROR_TXFAIL 0x00000800U /*!< Transmit failure */ +/** + * @} + */ + +/** @defgroup CAN_InitStatus CAN InitStatus + * @{ + */ +#define CAN_INITSTATUS_FAILED ((uint8_t)0x00) /*!< CAN initialization failed */ +#define CAN_INITSTATUS_SUCCESS ((uint8_t)0x01) /*!< CAN initialization OK */ +/** + * @} + */ + +/** @defgroup CAN_operating_mode CAN Operating Mode + * @{ + */ +#define CAN_MODE_NORMAL 0x00000000U /*!< Normal mode */ +#define CAN_MODE_LOOPBACK ((uint32_t)CAN_BTR_LBKM) /*!< Loopback mode */ +#define CAN_MODE_SILENT ((uint32_t)CAN_BTR_SILM) /*!< Silent mode */ +#define CAN_MODE_SILENT_LOOPBACK ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM)) /*!< Loopback combined with silent mode */ +/** + * @} + */ + +/** @defgroup CAN_synchronisation_jump_width CAN Synchronisation Jump Width + * @{ + */ +#define CAN_SJW_1TQ 0x00000000U /*!< 1 time quantum */ +#define CAN_SJW_2TQ ((uint32_t)CAN_BTR_SJW_0) /*!< 2 time quantum */ +#define CAN_SJW_3TQ ((uint32_t)CAN_BTR_SJW_1) /*!< 3 time quantum */ +#define CAN_SJW_4TQ ((uint32_t)CAN_BTR_SJW) /*!< 4 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_1 CAN Time Quantum in bit segment 1 + * @{ + */ +#define CAN_BS1_1TQ 0x00000000U /*!< 1 time quantum */ +#define CAN_BS1_2TQ ((uint32_t)CAN_BTR_TS1_0) /*!< 2 time quantum */ +#define CAN_BS1_3TQ ((uint32_t)CAN_BTR_TS1_1) /*!< 3 time quantum */ +#define CAN_BS1_4TQ ((uint32_t)(CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 4 time quantum */ +#define CAN_BS1_5TQ ((uint32_t)CAN_BTR_TS1_2) /*!< 5 time quantum */ +#define CAN_BS1_6TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 6 time quantum */ +#define CAN_BS1_7TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 7 time quantum */ +#define CAN_BS1_8TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 8 time quantum */ +#define CAN_BS1_9TQ ((uint32_t)CAN_BTR_TS1_3) /*!< 9 time quantum */ +#define CAN_BS1_10TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_0)) /*!< 10 time quantum */ +#define CAN_BS1_11TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1)) /*!< 11 time quantum */ +#define CAN_BS1_12TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 12 time quantum */ +#define CAN_BS1_13TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2)) /*!< 13 time quantum */ +#define CAN_BS1_14TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 14 time quantum */ +#define CAN_BS1_15TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 15 time quantum */ +#define CAN_BS1_16TQ ((uint32_t)CAN_BTR_TS1) /*!< 16 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_2 CAN Time Quantum in bit segment 2 + * @{ + */ +#define CAN_BS2_1TQ 0x00000000U /*!< 1 time quantum */ +#define CAN_BS2_2TQ ((uint32_t)CAN_BTR_TS2_0) /*!< 2 time quantum */ +#define CAN_BS2_3TQ ((uint32_t)CAN_BTR_TS2_1) /*!< 3 time quantum */ +#define CAN_BS2_4TQ ((uint32_t)(CAN_BTR_TS2_1 | CAN_BTR_TS2_0)) /*!< 4 time quantum */ +#define CAN_BS2_5TQ ((uint32_t)CAN_BTR_TS2_2) /*!< 5 time quantum */ +#define CAN_BS2_6TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_0)) /*!< 6 time quantum */ +#define CAN_BS2_7TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_1)) /*!< 7 time quantum */ +#define CAN_BS2_8TQ ((uint32_t)CAN_BTR_TS2) /*!< 8 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_filter_mode CAN Filter Mode + * @{ + */ +#define CAN_FILTERMODE_IDMASK ((uint8_t)0x00) /*!< Identifier mask mode */ +#define CAN_FILTERMODE_IDLIST ((uint8_t)0x01) /*!< Identifier list mode */ +/** + * @} + */ + +/** @defgroup CAN_filter_scale CAN Filter Scale + * @{ + */ +#define CAN_FILTERSCALE_16BIT ((uint8_t)0x00) /*!< Two 16-bit filters */ +#define CAN_FILTERSCALE_32BIT ((uint8_t)0x01) /*!< One 32-bit filter */ +/** + * @} + */ + +/** @defgroup CAN_filter_FIFO CAN Filter FIFO + * @{ + */ +#define CAN_FILTER_FIFO0 ((uint8_t)0x00) /*!< Filter FIFO 0 assignment for filter x */ +#define CAN_FILTER_FIFO1 ((uint8_t)0x01) /*!< Filter FIFO 1 assignment for filter x */ +/** + * @} + */ + +/** @defgroup CAN_Identifier_Type CAN Identifier Type + * @{ + */ +#define CAN_ID_STD 0x00000000U /*!< Standard Id */ +#define CAN_ID_EXT 0x00000004U /*!< Extended Id */ +/** + * @} + */ + +/** @defgroup CAN_remote_transmission_request CAN Remote Transmission Request + * @{ + */ +#define CAN_RTR_DATA 0x00000000U /*!< Data frame */ +#define CAN_RTR_REMOTE 0x00000002U /*!< Remote frame */ +/** + * @} + */ + +/** @defgroup CAN_receive_FIFO_number_constants CAN Receive FIFO Number Constants + * @{ + */ +#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN FIFO 0 used to receive */ +#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN FIFO 1 used to receive */ +/** + * @} + */ + +/** @defgroup CAN_flags CAN Flags + * @{ + */ +/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagStatus() + and CAN_ClearFlag() functions. */ +/* If the flag is 0x1XXXXXXX, it means that it can only be used with + CAN_GetFlagStatus() function. */ + +/* Transmit Flags */ +#define CAN_FLAG_RQCP0 0x00000500U /*!< Request MailBox0 flag */ +#define CAN_FLAG_RQCP1 0x00000508U /*!< Request MailBox1 flag */ +#define CAN_FLAG_RQCP2 0x00000510U /*!< Request MailBox2 flag */ +#define CAN_FLAG_TXOK0 0x00000501U /*!< Transmission OK MailBox0 flag */ +#define CAN_FLAG_TXOK1 0x00000509U /*!< Transmission OK MailBox1 flag */ +#define CAN_FLAG_TXOK2 0x00000511U /*!< Transmission OK MailBox2 flag */ +#define CAN_FLAG_TME0 0x0000051AU /*!< Transmit mailbox 0 empty flag */ +#define CAN_FLAG_TME1 0x0000051BU /*!< Transmit mailbox 0 empty flag */ +#define CAN_FLAG_TME2 0x0000051CU /*!< Transmit mailbox 0 empty flag */ + +/* Receive Flags */ +#define CAN_FLAG_FF0 0x00000203U /*!< FIFO 0 Full flag */ +#define CAN_FLAG_FOV0 0x00000204U /*!< FIFO 0 Overrun flag */ + +#define CAN_FLAG_FF1 0x00000403U /*!< FIFO 1 Full flag */ +#define CAN_FLAG_FOV1 0x00000404U /*!< FIFO 1 Overrun flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_INAK 0x00000100U /*!< Initialization acknowledge flag */ +#define CAN_FLAG_SLAK 0x00000101U /*!< Sleep acknowledge flag */ +#define CAN_FLAG_ERRI 0x00000102U /*!< Error flag */ +#define CAN_FLAG_WKU 0x00000103U /*!< Wake up flag */ +#define CAN_FLAG_SLAKI 0x00000104U /*!< Sleep acknowledge flag */ + +/* @note When SLAK interrupt is disabled (SLKIE=0), no polling on SLAKI is possible. + In this case the SLAK bit can be polled.*/ + +/* Error Flags */ +#define CAN_FLAG_EWG 0x00000300U /*!< Error warning flag */ +#define CAN_FLAG_EPV 0x00000301U /*!< Error passive flag */ +#define CAN_FLAG_BOF 0x00000302U /*!< Bus-Off flag */ +/** + * @} + */ + +/** @defgroup CAN_Interrupts CAN Interrupts + * @{ + */ +#define CAN_IT_TME ((uint32_t)CAN_IER_TMEIE) /*!< Transmit mailbox empty interrupt */ + +/* Receive Interrupts */ +#define CAN_IT_FMP0 ((uint32_t)CAN_IER_FMPIE0) /*!< FIFO 0 message pending interrupt */ +#define CAN_IT_FF0 ((uint32_t)CAN_IER_FFIE0) /*!< FIFO 0 full interrupt */ +#define CAN_IT_FOV0 ((uint32_t)CAN_IER_FOVIE0) /*!< FIFO 0 overrun interrupt */ +#define CAN_IT_FMP1 ((uint32_t)CAN_IER_FMPIE1) /*!< FIFO 1 message pending interrupt */ +#define CAN_IT_FF1 ((uint32_t)CAN_IER_FFIE1) /*!< FIFO 1 full interrupt */ +#define CAN_IT_FOV1 ((uint32_t)CAN_IER_FOVIE1) /*!< FIFO 1 overrun interrupt */ + +/* Operating Mode Interrupts */ +#define CAN_IT_WKU ((uint32_t)CAN_IER_WKUIE) /*!< Wake-up interrupt */ +#define CAN_IT_SLK ((uint32_t)CAN_IER_SLKIE) /*!< Sleep acknowledge interrupt */ + +/* Error Interrupts */ +#define CAN_IT_EWG ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt */ +#define CAN_IT_EPV ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt */ +#define CAN_IT_BOF ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt */ +#define CAN_IT_LEC ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */ +#define CAN_IT_ERR ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt */ +/** + * @} + */ + +/** @defgroup CAN_Mailboxes_Definition CAN Mailboxes Definition + * @{ + */ +#define CAN_TXMAILBOX_0 ((uint8_t)0x00) +#define CAN_TXMAILBOX_1 ((uint8_t)0x01) +#define CAN_TXMAILBOX_2 ((uint8_t)0x02) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup CAN_Exported_Macros CAN Exported Macros + * @{ + */ + +/** @brief Reset CAN handle state + * @param __HANDLE__ specifies the CAN Handle. + * @retval None + */ +#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CAN_STATE_RESET) + +/** + * @brief Enable the specified CAN interrupts. + * @param __HANDLE__ CAN handle + * @param __INTERRUPT__ CAN Interrupt + * @retval None + */ +#define __HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) |= (__INTERRUPT__)) + +/** + * @brief Disable the specified CAN interrupts. + * @param __HANDLE__ CAN handle + * @param __INTERRUPT__ CAN Interrupt + * @retval None + */ +#define __HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) &= ~(__INTERRUPT__)) + +/** + * @brief Return the number of pending received messages. + * @param __HANDLE__ CAN handle + * @param __FIFONUMBER__ Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. + * @retval The number of pending message. + */ +#define __HAL_CAN_MSG_PENDING(__HANDLE__, __FIFONUMBER__) (((__FIFONUMBER__) == CAN_FIFO0)? \ +((uint8_t)((__HANDLE__)->Instance->RF0R&0x03U)) : ((uint8_t)((__HANDLE__)->Instance->RF1R & 0x03U))) + +/** @brief Check whether the specified CAN flag is set or not. + * @param __HANDLE__ CAN Handle + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg CAN_TSR_RQCP0: Request MailBox0 Flag + * @arg CAN_TSR_RQCP1: Request MailBox1 Flag + * @arg CAN_TSR_RQCP2: Request MailBox2 Flag + * @arg CAN_FLAG_TXOK0: Transmission OK MailBox0 Flag + * @arg CAN_FLAG_TXOK1: Transmission OK MailBox1 Flag + * @arg CAN_FLAG_TXOK2: Transmission OK MailBox2 Flag + * @arg CAN_FLAG_TME0: Transmit mailbox 0 empty Flag + * @arg CAN_FLAG_TME1: Transmit mailbox 1 empty Flag + * @arg CAN_FLAG_TME2: Transmit mailbox 2 empty Flag + * @arg CAN_FLAG_FMP0: FIFO 0 Message Pending Flag + * @arg CAN_FLAG_FF0: FIFO 0 Full Flag + * @arg CAN_FLAG_FOV0: FIFO 0 Overrun Flag + * @arg CAN_FLAG_FMP1: FIFO 1 Message Pending Flag + * @arg CAN_FLAG_FF1: FIFO 1 Full Flag + * @arg CAN_FLAG_FOV1: FIFO 1 Overrun Flag + * @arg CAN_FLAG_WKU: Wake up Flag + * @arg CAN_FLAG_SLAK: Sleep acknowledge Flag + * @arg CAN_FLAG_SLAKI: Sleep acknowledge Flag + * @arg CAN_FLAG_EWG: Error Warning Flag + * @arg CAN_FLAG_EPV: Error Passive Flag + * @arg CAN_FLAG_BOF: Bus-Off Flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_CAN_GET_FLAG(__HANDLE__, __FLAG__) \ +((((__FLAG__) >> 8U) == 5U)? ((((__HANDLE__)->Instance->TSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 2U)? ((((__HANDLE__)->Instance->RF0R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 4U)? ((((__HANDLE__)->Instance->RF1R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 1U)? ((((__HANDLE__)->Instance->MSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + ((((__HANDLE__)->Instance->ESR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK)))) + +/** @brief Clear the specified CAN pending flag. + * @param __HANDLE__ CAN Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg CAN_TSR_RQCP0: Request MailBox0 Flag + * @arg CAN_TSR_RQCP1: Request MailBox1 Flag + * @arg CAN_TSR_RQCP2: Request MailBox2 Flag + * @arg CAN_FLAG_TXOK0: Transmission OK MailBox0 Flag + * @arg CAN_FLAG_TXOK1: Transmission OK MailBox1 Flag + * @arg CAN_FLAG_TXOK2: Transmission OK MailBox2 Flag + * @arg CAN_FLAG_TME0: Transmit mailbox 0 empty Flag + * @arg CAN_FLAG_TME1: Transmit mailbox 1 empty Flag + * @arg CAN_FLAG_TME2: Transmit mailbox 2 empty Flag + * @arg CAN_FLAG_FMP0: FIFO 0 Message Pending Flag + * @arg CAN_FLAG_FF0: FIFO 0 Full Flag + * @arg CAN_FLAG_FOV0: FIFO 0 Overrun Flag + * @arg CAN_FLAG_FMP1: FIFO 1 Message Pending Flag + * @arg CAN_FLAG_FF1: FIFO 1 Full Flag + * @arg CAN_FLAG_FOV1: FIFO 1 Overrun Flag + * @arg CAN_FLAG_WKU: Wake up Flag + * @arg CAN_FLAG_SLAK: Sleep acknowledge Flag + * @arg CAN_FLAG_SLAKI: Sleep acknowledge Flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_CAN_CLEAR_FLAG(__HANDLE__, __FLAG__) \ +((((__FLAG__) >> 8U) == 5U)? (((__HANDLE__)->Instance->TSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 2U)? (((__HANDLE__)->Instance->RF0R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 4U)? (((__HANDLE__)->Instance->RF1R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__HANDLE__)->Instance->MSR) = ((uint32_t)1U << ((__FLAG__) & CAN_FLAG_MASK)))) + +/** @brief Check if the specified CAN interrupt source is enabled or disabled. + * @param __HANDLE__ CAN Handle + * @param __INTERRUPT__ specifies the CAN interrupt source to check. + * This parameter can be one of the following values: + * @arg CAN_IT_TME: Transmit mailbox empty interrupt enable + * @arg CAN_IT_FMP0: FIFO0 message pending interrupt enable + * @arg CAN_IT_FMP1: FIFO1 message pending interrupt enable + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_CAN_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->IER & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** + * @brief Check the transmission status of a CAN Frame. + * @param __HANDLE__ CAN Handle + * @param __TRANSMITMAILBOX__ the number of the mailbox that is used for transmission. + * @retval The new status of transmission (TRUE or FALSE). + */ +#define __HAL_CAN_TRANSMIT_STATUS(__HANDLE__, __TRANSMITMAILBOX__)\ +(((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_0)? ((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0)) == (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0)) :\ + ((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_1)? ((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1)) == (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1)) :\ + ((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2)) == (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2))) + +/** + * @brief Release the specified receive FIFO. + * @param __HANDLE__ CAN handle + * @param __FIFONUMBER__ Receive FIFO number, CAN_FIFO0 or CAN_FIFO1. + * @retval None + */ +#define __HAL_CAN_FIFO_RELEASE(__HANDLE__, __FIFONUMBER__) (((__FIFONUMBER__) == CAN_FIFO0)? \ +((__HANDLE__)->Instance->RF0R = CAN_RF0R_RFOM0) : ((__HANDLE__)->Instance->RF1R = CAN_RF1R_RFOM1)) + +/** + * @brief Cancel a transmit request. + * @param __HANDLE__ CAN Handle + * @param __TRANSMITMAILBOX__ the number of the mailbox that is used for transmission. + * @retval None + */ +#define __HAL_CAN_CANCEL_TRANSMIT(__HANDLE__, __TRANSMITMAILBOX__)\ +(((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_0)? ((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ0) :\ + ((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_1)? ((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ1) :\ + ((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ2)) + +/** + * @brief Enable or disable the DBG Freeze for CAN. + * @param __HANDLE__ CAN Handle + * @param __NEWSTATE__ new state of the CAN peripheral. + * This parameter can be: ENABLE (CAN reception/transmission is frozen + * during debug. Reception FIFOs can still be accessed/controlled normally) + * or DISABLE (CAN is working during debug). + * @retval None + */ +#define __HAL_CAN_DBG_FREEZE(__HANDLE__, __NEWSTATE__) (((__NEWSTATE__) == ENABLE)? \ +((__HANDLE__)->Instance->MCR |= CAN_MCR_DBF) : ((__HANDLE__)->Instance->MCR &= ~CAN_MCR_DBF)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup CAN_Exported_Functions + * @{ + */ + +/** @addtogroup CAN_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ***********************************/ +HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan); +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig); +HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan); +void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan); +void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan); +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ******************************************************/ +HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); +HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, uint8_t FIFONumber, uint32_t Timeout); +HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef *hcan, uint8_t FIFONumber); +HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan); +void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan); +void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan); +void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan); +void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan); +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions ***************************************************/ +uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan); +HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup CAN_Private_Types CAN Private Types + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup CAN_Private_Variables CAN Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup CAN_Private_Constants CAN Private Constants + * @{ + */ +#define CAN_TXSTATUS_NOMAILBOX ((uint8_t)0x04) /*!< CAN cell did not provide CAN_TxStatus_NoMailBox */ +#define CAN_FLAG_MASK 0x000000FFU +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup CAN_Private_Macros CAN Private Macros + * @{ + */ +#define IS_CAN_MODE(MODE) (((MODE) == CAN_MODE_NORMAL) || \ + ((MODE) == CAN_MODE_LOOPBACK)|| \ + ((MODE) == CAN_MODE_SILENT) || \ + ((MODE) == CAN_MODE_SILENT_LOOPBACK)) +#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1TQ) || ((SJW) == CAN_SJW_2TQ)|| \ + ((SJW) == CAN_SJW_3TQ) || ((SJW) == CAN_SJW_4TQ)) +#define IS_CAN_BS1(BS1) ((BS1) <= CAN_BS1_16TQ) +#define IS_CAN_BS2(BS2) ((BS2) <= CAN_BS2_8TQ) +#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1U) && ((PRESCALER) <= 1024U)) +#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 27U) +#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FILTERMODE_IDMASK) || \ + ((MODE) == CAN_FILTERMODE_IDLIST)) +#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FILTERSCALE_16BIT) || \ + ((SCALE) == CAN_FILTERSCALE_32BIT)) +#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FILTER_FIFO0) || \ + ((FIFO) == CAN_FILTER_FIFO1)) +#define IS_CAN_BANKNUMBER(BANKNUMBER) ((BANKNUMBER) <= 28U) + +#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02)) +#define IS_CAN_STDID(STDID) ((STDID) <= ((uint32_t)0x7FFU)) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU) +#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08)) + +#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_ID_STD) || \ + ((IDTYPE) == CAN_ID_EXT)) +#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_DATA) || ((RTR) == CAN_RTR_REMOTE)) +#define IS_CAN_FIFO(FIFO) (((FIFO) == CAN_FIFO0) || ((FIFO) == CAN_FIFO1)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup CAN_Private_Functions CAN Private Functions + * @{ + */ + +/** + * @} + */ + +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx ||\ + STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CAN_LEGACY_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_eth_legacy.h b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_eth_legacy.h new file mode 100644 index 0000000..ab84a46 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/Legacy/stm32f4xx_hal_eth_legacy.h @@ -0,0 +1,2209 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth_legacy.h + * @author MCD Application Team + * @brief Header file of ETH HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_ETH_LEGACY_H +#define __STM32F4xx_HAL_ETH_LEGACY_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/** @addtogroup ETH_Private_Macros + * @{ + */ +#define IS_ETH_PHY_ADDRESS(ADDRESS) ((ADDRESS) <= 0x20U) +#define IS_ETH_AUTONEGOTIATION(CMD) (((CMD) == ETH_AUTONEGOTIATION_ENABLE) || \ + ((CMD) == ETH_AUTONEGOTIATION_DISABLE)) +#define IS_ETH_SPEED(SPEED) (((SPEED) == ETH_SPEED_10M) || \ + ((SPEED) == ETH_SPEED_100M)) +#define IS_ETH_DUPLEX_MODE(MODE) (((MODE) == ETH_MODE_FULLDUPLEX) || \ + ((MODE) == ETH_MODE_HALFDUPLEX)) +#define IS_ETH_RX_MODE(MODE) (((MODE) == ETH_RXPOLLING_MODE) || \ + ((MODE) == ETH_RXINTERRUPT_MODE)) +#define IS_ETH_CHECKSUM_MODE(MODE) (((MODE) == ETH_CHECKSUM_BY_HARDWARE) || \ + ((MODE) == ETH_CHECKSUM_BY_SOFTWARE)) +#define IS_ETH_MEDIA_INTERFACE(MODE) (((MODE) == ETH_MEDIA_INTERFACE_MII) || \ + ((MODE) == ETH_MEDIA_INTERFACE_RMII)) +#define IS_ETH_WATCHDOG(CMD) (((CMD) == ETH_WATCHDOG_ENABLE) || \ + ((CMD) == ETH_WATCHDOG_DISABLE)) +#define IS_ETH_JABBER(CMD) (((CMD) == ETH_JABBER_ENABLE) || \ + ((CMD) == ETH_JABBER_DISABLE)) +#define IS_ETH_INTER_FRAME_GAP(GAP) (((GAP) == ETH_INTERFRAMEGAP_96BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_88BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_80BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_72BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_64BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_56BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_48BIT) || \ + ((GAP) == ETH_INTERFRAMEGAP_40BIT)) +#define IS_ETH_CARRIER_SENSE(CMD) (((CMD) == ETH_CARRIERSENCE_ENABLE) || \ + ((CMD) == ETH_CARRIERSENCE_DISABLE)) +#define IS_ETH_RECEIVE_OWN(CMD) (((CMD) == ETH_RECEIVEOWN_ENABLE) || \ + ((CMD) == ETH_RECEIVEOWN_DISABLE)) +#define IS_ETH_LOOPBACK_MODE(CMD) (((CMD) == ETH_LOOPBACKMODE_ENABLE) || \ + ((CMD) == ETH_LOOPBACKMODE_DISABLE)) +#define IS_ETH_CHECKSUM_OFFLOAD(CMD) (((CMD) == ETH_CHECKSUMOFFLAOD_ENABLE) || \ + ((CMD) == ETH_CHECKSUMOFFLAOD_DISABLE)) +#define IS_ETH_RETRY_TRANSMISSION(CMD) (((CMD) == ETH_RETRYTRANSMISSION_ENABLE) || \ + ((CMD) == ETH_RETRYTRANSMISSION_DISABLE)) +#define IS_ETH_AUTOMATIC_PADCRC_STRIP(CMD) (((CMD) == ETH_AUTOMATICPADCRCSTRIP_ENABLE) || \ + ((CMD) == ETH_AUTOMATICPADCRCSTRIP_DISABLE)) +#define IS_ETH_BACKOFF_LIMIT(LIMIT) (((LIMIT) == ETH_BACKOFFLIMIT_10) || \ + ((LIMIT) == ETH_BACKOFFLIMIT_8) || \ + ((LIMIT) == ETH_BACKOFFLIMIT_4) || \ + ((LIMIT) == ETH_BACKOFFLIMIT_1)) +#define IS_ETH_DEFERRAL_CHECK(CMD) (((CMD) == ETH_DEFFERRALCHECK_ENABLE) || \ + ((CMD) == ETH_DEFFERRALCHECK_DISABLE)) +#define IS_ETH_RECEIVE_ALL(CMD) (((CMD) == ETH_RECEIVEALL_ENABLE) || \ + ((CMD) == ETH_RECEIVEAll_DISABLE)) +#define IS_ETH_SOURCE_ADDR_FILTER(CMD) (((CMD) == ETH_SOURCEADDRFILTER_NORMAL_ENABLE) || \ + ((CMD) == ETH_SOURCEADDRFILTER_INVERSE_ENABLE) || \ + ((CMD) == ETH_SOURCEADDRFILTER_DISABLE)) +#define IS_ETH_CONTROL_FRAMES(PASS) (((PASS) == ETH_PASSCONTROLFRAMES_BLOCKALL) || \ + ((PASS) == ETH_PASSCONTROLFRAMES_FORWARDALL) || \ + ((PASS) == ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER)) +#define IS_ETH_BROADCAST_FRAMES_RECEPTION(CMD) (((CMD) == ETH_BROADCASTFRAMESRECEPTION_ENABLE) || \ + ((CMD) == ETH_BROADCASTFRAMESRECEPTION_DISABLE)) +#define IS_ETH_DESTINATION_ADDR_FILTER(FILTER) (((FILTER) == ETH_DESTINATIONADDRFILTER_NORMAL) || \ + ((FILTER) == ETH_DESTINATIONADDRFILTER_INVERSE)) +#define IS_ETH_PROMISCUOUS_MODE(CMD) (((CMD) == ETH_PROMISCUOUS_MODE_ENABLE) || \ + ((CMD) == ETH_PROMISCUOUS_MODE_DISABLE)) +#define IS_ETH_MULTICAST_FRAMES_FILTER(FILTER) (((FILTER) == ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE) || \ + ((FILTER) == ETH_MULTICASTFRAMESFILTER_HASHTABLE) || \ + ((FILTER) == ETH_MULTICASTFRAMESFILTER_PERFECT) || \ + ((FILTER) == ETH_MULTICASTFRAMESFILTER_NONE)) +#define IS_ETH_UNICAST_FRAMES_FILTER(FILTER) (((FILTER) == ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE) || \ + ((FILTER) == ETH_UNICASTFRAMESFILTER_HASHTABLE) || \ + ((FILTER) == ETH_UNICASTFRAMESFILTER_PERFECT)) +#define IS_ETH_PAUSE_TIME(TIME) ((TIME) <= 0xFFFFU) +#define IS_ETH_ZEROQUANTA_PAUSE(CMD) (((CMD) == ETH_ZEROQUANTAPAUSE_ENABLE) || \ + ((CMD) == ETH_ZEROQUANTAPAUSE_DISABLE)) +#define IS_ETH_PAUSE_LOW_THRESHOLD(THRESHOLD) (((THRESHOLD) == ETH_PAUSELOWTHRESHOLD_MINUS4) || \ + ((THRESHOLD) == ETH_PAUSELOWTHRESHOLD_MINUS28) || \ + ((THRESHOLD) == ETH_PAUSELOWTHRESHOLD_MINUS144) || \ + ((THRESHOLD) == ETH_PAUSELOWTHRESHOLD_MINUS256)) +#define IS_ETH_UNICAST_PAUSE_FRAME_DETECT(CMD) (((CMD) == ETH_UNICASTPAUSEFRAMEDETECT_ENABLE) || \ + ((CMD) == ETH_UNICASTPAUSEFRAMEDETECT_DISABLE)) +#define IS_ETH_RECEIVE_FLOWCONTROL(CMD) (((CMD) == ETH_RECEIVEFLOWCONTROL_ENABLE) || \ + ((CMD) == ETH_RECEIVEFLOWCONTROL_DISABLE)) +#define IS_ETH_TRANSMIT_FLOWCONTROL(CMD) (((CMD) == ETH_TRANSMITFLOWCONTROL_ENABLE) || \ + ((CMD) == ETH_TRANSMITFLOWCONTROL_DISABLE)) +#define IS_ETH_VLAN_TAG_COMPARISON(COMPARISON) (((COMPARISON) == ETH_VLANTAGCOMPARISON_12BIT) || \ + ((COMPARISON) == ETH_VLANTAGCOMPARISON_16BIT)) +#define IS_ETH_VLAN_TAG_IDENTIFIER(IDENTIFIER) ((IDENTIFIER) <= 0xFFFFU) +#define IS_ETH_MAC_ADDRESS0123(ADDRESS) (((ADDRESS) == ETH_MAC_ADDRESS0) || \ + ((ADDRESS) == ETH_MAC_ADDRESS1) || \ + ((ADDRESS) == ETH_MAC_ADDRESS2) || \ + ((ADDRESS) == ETH_MAC_ADDRESS3)) +#define IS_ETH_MAC_ADDRESS123(ADDRESS) (((ADDRESS) == ETH_MAC_ADDRESS1) || \ + ((ADDRESS) == ETH_MAC_ADDRESS2) || \ + ((ADDRESS) == ETH_MAC_ADDRESS3)) +#define IS_ETH_MAC_ADDRESS_FILTER(FILTER) (((FILTER) == ETH_MAC_ADDRESSFILTER_SA) || \ + ((FILTER) == ETH_MAC_ADDRESSFILTER_DA)) +#define IS_ETH_MAC_ADDRESS_MASK(MASK) (((MASK) == ETH_MAC_ADDRESSMASK_BYTE6) || \ + ((MASK) == ETH_MAC_ADDRESSMASK_BYTE5) || \ + ((MASK) == ETH_MAC_ADDRESSMASK_BYTE4) || \ + ((MASK) == ETH_MAC_ADDRESSMASK_BYTE3) || \ + ((MASK) == ETH_MAC_ADDRESSMASK_BYTE2) || \ + ((MASK) == ETH_MAC_ADDRESSMASK_BYTE1)) +#define IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(CMD) (((CMD) == ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE) || \ + ((CMD) == ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE)) +#define IS_ETH_RECEIVE_STORE_FORWARD(CMD) (((CMD) == ETH_RECEIVESTOREFORWARD_ENABLE) || \ + ((CMD) == ETH_RECEIVESTOREFORWARD_DISABLE)) +#define IS_ETH_FLUSH_RECEIVE_FRAME(CMD) (((CMD) == ETH_FLUSHRECEIVEDFRAME_ENABLE) || \ + ((CMD) == ETH_FLUSHRECEIVEDFRAME_DISABLE)) +#define IS_ETH_TRANSMIT_STORE_FORWARD(CMD) (((CMD) == ETH_TRANSMITSTOREFORWARD_ENABLE) || \ + ((CMD) == ETH_TRANSMITSTOREFORWARD_DISABLE)) +#define IS_ETH_TRANSMIT_THRESHOLD_CONTROL(THRESHOLD) (((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_64BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_128BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_192BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_256BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_40BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_32BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_24BYTES) || \ + ((THRESHOLD) == ETH_TRANSMITTHRESHOLDCONTROL_16BYTES)) +#define IS_ETH_FORWARD_ERROR_FRAMES(CMD) (((CMD) == ETH_FORWARDERRORFRAMES_ENABLE) || \ + ((CMD) == ETH_FORWARDERRORFRAMES_DISABLE)) +#define IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(CMD) (((CMD) == ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE) || \ + ((CMD) == ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE)) +#define IS_ETH_RECEIVE_THRESHOLD_CONTROL(THRESHOLD) (((THRESHOLD) == ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES) || \ + ((THRESHOLD) == ETH_RECEIVEDTHRESHOLDCONTROL_32BYTES) || \ + ((THRESHOLD) == ETH_RECEIVEDTHRESHOLDCONTROL_96BYTES) || \ + ((THRESHOLD) == ETH_RECEIVEDTHRESHOLDCONTROL_128BYTES)) +#define IS_ETH_SECOND_FRAME_OPERATE(CMD) (((CMD) == ETH_SECONDFRAMEOPERARTE_ENABLE) || \ + ((CMD) == ETH_SECONDFRAMEOPERARTE_DISABLE)) +#define IS_ETH_ADDRESS_ALIGNED_BEATS(CMD) (((CMD) == ETH_ADDRESSALIGNEDBEATS_ENABLE) || \ + ((CMD) == ETH_ADDRESSALIGNEDBEATS_DISABLE)) +#define IS_ETH_FIXED_BURST(CMD) (((CMD) == ETH_FIXEDBURST_ENABLE) || \ + ((CMD) == ETH_FIXEDBURST_DISABLE)) +#define IS_ETH_RXDMA_BURST_LENGTH(LENGTH) (((LENGTH) == ETH_RXDMABURSTLENGTH_1BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_2BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_8BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_16BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_32BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_4BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_8BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_16BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_32BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_64BEAT) || \ + ((LENGTH) == ETH_RXDMABURSTLENGTH_4XPBL_128BEAT)) +#define IS_ETH_TXDMA_BURST_LENGTH(LENGTH) (((LENGTH) == ETH_TXDMABURSTLENGTH_1BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_2BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_8BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_16BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_32BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_4BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_8BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_16BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_32BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_64BEAT) || \ + ((LENGTH) == ETH_TXDMABURSTLENGTH_4XPBL_128BEAT)) +#define IS_ETH_DMA_DESC_SKIP_LENGTH(LENGTH) ((LENGTH) <= 0x1FU) +#define IS_ETH_DMA_ARBITRATION_ROUNDROBIN_RXTX(RATIO) (((RATIO) == ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1) || \ + ((RATIO) == ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1) || \ + ((RATIO) == ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1) || \ + ((RATIO) == ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1) || \ + ((RATIO) == ETH_DMAARBITRATION_RXPRIORTX)) +#define IS_ETH_DMATXDESC_GET_FLAG(FLAG) (((FLAG) == ETH_DMATXDESC_OWN) || \ + ((FLAG) == ETH_DMATXDESC_IC) || \ + ((FLAG) == ETH_DMATXDESC_LS) || \ + ((FLAG) == ETH_DMATXDESC_FS) || \ + ((FLAG) == ETH_DMATXDESC_DC) || \ + ((FLAG) == ETH_DMATXDESC_DP) || \ + ((FLAG) == ETH_DMATXDESC_TTSE) || \ + ((FLAG) == ETH_DMATXDESC_TER) || \ + ((FLAG) == ETH_DMATXDESC_TCH) || \ + ((FLAG) == ETH_DMATXDESC_TTSS) || \ + ((FLAG) == ETH_DMATXDESC_IHE) || \ + ((FLAG) == ETH_DMATXDESC_ES) || \ + ((FLAG) == ETH_DMATXDESC_JT) || \ + ((FLAG) == ETH_DMATXDESC_FF) || \ + ((FLAG) == ETH_DMATXDESC_PCE) || \ + ((FLAG) == ETH_DMATXDESC_LCA) || \ + ((FLAG) == ETH_DMATXDESC_NC) || \ + ((FLAG) == ETH_DMATXDESC_LCO) || \ + ((FLAG) == ETH_DMATXDESC_EC) || \ + ((FLAG) == ETH_DMATXDESC_VF) || \ + ((FLAG) == ETH_DMATXDESC_CC) || \ + ((FLAG) == ETH_DMATXDESC_ED) || \ + ((FLAG) == ETH_DMATXDESC_UF) || \ + ((FLAG) == ETH_DMATXDESC_DB)) +#define IS_ETH_DMA_TXDESC_SEGMENT(SEGMENT) (((SEGMENT) == ETH_DMATXDESC_LASTSEGMENTS) || \ + ((SEGMENT) == ETH_DMATXDESC_FIRSTSEGMENT)) +#define IS_ETH_DMA_TXDESC_CHECKSUM(CHECKSUM) (((CHECKSUM) == ETH_DMATXDESC_CHECKSUMBYPASS) || \ + ((CHECKSUM) == ETH_DMATXDESC_CHECKSUMIPV4HEADER) || \ + ((CHECKSUM) == ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT) || \ + ((CHECKSUM) == ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL)) +#define IS_ETH_DMATXDESC_BUFFER_SIZE(SIZE) ((SIZE) <= 0x1FFFU) +#define IS_ETH_DMARXDESC_GET_FLAG(FLAG) (((FLAG) == ETH_DMARXDESC_OWN) || \ + ((FLAG) == ETH_DMARXDESC_AFM) || \ + ((FLAG) == ETH_DMARXDESC_ES) || \ + ((FLAG) == ETH_DMARXDESC_DE) || \ + ((FLAG) == ETH_DMARXDESC_SAF) || \ + ((FLAG) == ETH_DMARXDESC_LE) || \ + ((FLAG) == ETH_DMARXDESC_OE) || \ + ((FLAG) == ETH_DMARXDESC_VLAN) || \ + ((FLAG) == ETH_DMARXDESC_FS) || \ + ((FLAG) == ETH_DMARXDESC_LS) || \ + ((FLAG) == ETH_DMARXDESC_IPV4HCE) || \ + ((FLAG) == ETH_DMARXDESC_LC) || \ + ((FLAG) == ETH_DMARXDESC_FT) || \ + ((FLAG) == ETH_DMARXDESC_RWT) || \ + ((FLAG) == ETH_DMARXDESC_RE) || \ + ((FLAG) == ETH_DMARXDESC_DBE) || \ + ((FLAG) == ETH_DMARXDESC_CE) || \ + ((FLAG) == ETH_DMARXDESC_MAMPCE)) +#define IS_ETH_DMA_RXDESC_BUFFER(BUFFER) (((BUFFER) == ETH_DMARXDESC_BUFFER1) || \ + ((BUFFER) == ETH_DMARXDESC_BUFFER2)) +#define IS_ETH_PMT_GET_FLAG(FLAG) (((FLAG) == ETH_PMT_FLAG_WUFR) || \ + ((FLAG) == ETH_PMT_FLAG_MPR)) +#define IS_ETH_DMA_FLAG(FLAG) ((((FLAG) & 0xC7FE1800U) == 0x00U) && ((FLAG) != 0x00U)) +#define IS_ETH_DMA_GET_FLAG(FLAG) (((FLAG) == ETH_DMA_FLAG_TST) || ((FLAG) == ETH_DMA_FLAG_PMT) || \ + ((FLAG) == ETH_DMA_FLAG_MMC) || ((FLAG) == ETH_DMA_FLAG_DATATRANSFERERROR) || \ + ((FLAG) == ETH_DMA_FLAG_READWRITEERROR) || ((FLAG) == ETH_DMA_FLAG_ACCESSERROR) || \ + ((FLAG) == ETH_DMA_FLAG_NIS) || ((FLAG) == ETH_DMA_FLAG_AIS) || \ + ((FLAG) == ETH_DMA_FLAG_ER) || ((FLAG) == ETH_DMA_FLAG_FBE) || \ + ((FLAG) == ETH_DMA_FLAG_ET) || ((FLAG) == ETH_DMA_FLAG_RWT) || \ + ((FLAG) == ETH_DMA_FLAG_RPS) || ((FLAG) == ETH_DMA_FLAG_RBU) || \ + ((FLAG) == ETH_DMA_FLAG_R) || ((FLAG) == ETH_DMA_FLAG_TU) || \ + ((FLAG) == ETH_DMA_FLAG_RO) || ((FLAG) == ETH_DMA_FLAG_TJT) || \ + ((FLAG) == ETH_DMA_FLAG_TBU) || ((FLAG) == ETH_DMA_FLAG_TPS) || \ + ((FLAG) == ETH_DMA_FLAG_T)) +#define IS_ETH_MAC_IT(IT) ((((IT) & 0xFFFFFDF1U) == 0x00U) && ((IT) != 0x00U)) +#define IS_ETH_MAC_GET_IT(IT) (((IT) == ETH_MAC_IT_TST) || ((IT) == ETH_MAC_IT_MMCT) || \ + ((IT) == ETH_MAC_IT_MMCR) || ((IT) == ETH_MAC_IT_MMC) || \ + ((IT) == ETH_MAC_IT_PMT)) +#define IS_ETH_MAC_GET_FLAG(FLAG) (((FLAG) == ETH_MAC_FLAG_TST) || ((FLAG) == ETH_MAC_FLAG_MMCT) || \ + ((FLAG) == ETH_MAC_FLAG_MMCR) || ((FLAG) == ETH_MAC_FLAG_MMC) || \ + ((FLAG) == ETH_MAC_FLAG_PMT)) +#define IS_ETH_DMA_IT(IT) ((((IT) & 0xC7FE1800U) == 0x00U) && ((IT) != 0x00U)) +#define IS_ETH_DMA_GET_IT(IT) (((IT) == ETH_DMA_IT_TST) || ((IT) == ETH_DMA_IT_PMT) || \ + ((IT) == ETH_DMA_IT_MMC) || ((IT) == ETH_DMA_IT_NIS) || \ + ((IT) == ETH_DMA_IT_AIS) || ((IT) == ETH_DMA_IT_ER) || \ + ((IT) == ETH_DMA_IT_FBE) || ((IT) == ETH_DMA_IT_ET) || \ + ((IT) == ETH_DMA_IT_RWT) || ((IT) == ETH_DMA_IT_RPS) || \ + ((IT) == ETH_DMA_IT_RBU) || ((IT) == ETH_DMA_IT_R) || \ + ((IT) == ETH_DMA_IT_TU) || ((IT) == ETH_DMA_IT_RO) || \ + ((IT) == ETH_DMA_IT_TJT) || ((IT) == ETH_DMA_IT_TBU) || \ + ((IT) == ETH_DMA_IT_TPS) || ((IT) == ETH_DMA_IT_T)) +#define IS_ETH_DMA_GET_OVERFLOW(OVERFLOW) (((OVERFLOW) == ETH_DMA_OVERFLOW_RXFIFOCOUNTER) || \ + ((OVERFLOW) == ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER)) +#define IS_ETH_MMC_IT(IT) (((((IT) & 0xFFDF3FFFU) == 0x00U) || (((IT) & 0xEFFDFF9FU) == 0x00U)) && \ + ((IT) != 0x00U)) +#define IS_ETH_MMC_GET_IT(IT) (((IT) == ETH_MMC_IT_TGF) || ((IT) == ETH_MMC_IT_TGFMSC) || \ + ((IT) == ETH_MMC_IT_TGFSC) || ((IT) == ETH_MMC_IT_RGUF) || \ + ((IT) == ETH_MMC_IT_RFAE) || ((IT) == ETH_MMC_IT_RFCE)) +#define IS_ETH_ENHANCED_DESCRIPTOR_FORMAT(CMD) (((CMD) == ETH_DMAENHANCEDDESCRIPTOR_ENABLE) || \ + ((CMD) == ETH_DMAENHANCEDDESCRIPTOR_DISABLE)) + +/** + * @} + */ + +/** @addtogroup ETH_Private_Defines + * @{ + */ +/* Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY 0x00000001U + +/* ETHERNET Errors */ +#define ETH_SUCCESS 0U +#define ETH_ERROR 1U + +/* ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMATXDESC_COLLISION_COUNTSHIFT 3U + +/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMATXDESC_BUFFER2_SIZESHIFT 16U + +/* ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMARXDESC_FRAME_LENGTHSHIFT 16U + +/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMARXDESC_BUFFER2_SIZESHIFT 16U + +/* ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (uint32_t)(ETH_MAC_BASE + 0x40U) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (uint32_t)(ETH_MAC_BASE + 0x44U) /* ETHERNET MAC address low offset */ + +/* ETHERNET MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/* ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFF20810FU + +/* ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/* ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/* ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8U + +/* ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT 17U + /** + * @} + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_ETH_STATE_RESET = 0x00U, /*!< Peripheral not yet Initialized or disabled */ + HAL_ETH_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_ETH_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ + HAL_ETH_STATE_BUSY_TX = 0x12U, /*!< Data Transmission process is ongoing */ + HAL_ETH_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_ETH_STATE_BUSY_TX_RX = 0x32U, /*!< Data Transmission and Reception process is ongoing */ + HAL_ETH_STATE_BUSY_WR = 0x42U, /*!< Write process is ongoing */ + HAL_ETH_STATE_BUSY_RD = 0x82U, /*!< Read process is ongoing */ + HAL_ETH_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ + HAL_ETH_STATE_ERROR = 0x04U /*!< Reception process is ongoing */ +}HAL_ETH_StateTypeDef; + +/** + * @brief ETH Init Structure definition + */ + +typedef struct +{ + uint32_t AutoNegotiation; /*!< Selects or not the AutoNegotiation mode for the external PHY + The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) + and the mode (half/full-duplex). + This parameter can be a value of @ref ETH_AutoNegotiation */ + + uint32_t Speed; /*!< Sets the Ethernet speed: 10/100 Mbps. + This parameter can be a value of @ref ETH_Speed */ + + uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + This parameter can be a value of @ref ETH_Duplex_Mode */ + + uint16_t PhyAddress; /*!< Ethernet PHY address. + This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ + + uint8_t *MACAddr; /*!< MAC Address of used Hardware: must be pointer on an array of 6 bytes */ + + uint32_t RxMode; /*!< Selects the Ethernet Rx mode: Polling mode, Interrupt mode. + This parameter can be a value of @ref ETH_Rx_Mode */ + + uint32_t ChecksumMode; /*!< Selects if the checksum is check by hardware or by software. + This parameter can be a value of @ref ETH_Checksum_Mode */ + + uint32_t MediaInterface; /*!< Selects the media-independent interface or the reduced media-independent interface. + This parameter can be a value of @ref ETH_Media_Interface */ + +} ETH_InitTypeDef; + + + /** + * @brief ETH MAC Configuration Structure definition + */ + +typedef struct +{ + uint32_t Watchdog; /*!< Selects or not the Watchdog timer + When enabled, the MAC allows no more then 2048 bytes to be received. + When disabled, the MAC can receive up to 16384 bytes. + This parameter can be a value of @ref ETH_Watchdog */ + + uint32_t Jabber; /*!< Selects or not Jabber timer + When enabled, the MAC allows no more then 2048 bytes to be sent. + When disabled, the MAC can send up to 16384 bytes. + This parameter can be a value of @ref ETH_Jabber */ + + uint32_t InterFrameGap; /*!< Selects the minimum IFG between frames during transmission. + This parameter can be a value of @ref ETH_Inter_Frame_Gap */ + + uint32_t CarrierSense; /*!< Selects or not the Carrier Sense. + This parameter can be a value of @ref ETH_Carrier_Sense */ + + uint32_t ReceiveOwn; /*!< Selects or not the ReceiveOwn, + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode. + This parameter can be a value of @ref ETH_Receive_Own */ + + uint32_t LoopbackMode; /*!< Selects or not the internal MAC MII Loopback mode. + This parameter can be a value of @ref ETH_Loop_Back_Mode */ + + uint32_t ChecksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. + This parameter can be a value of @ref ETH_Checksum_Offload */ + + uint32_t RetryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a collision occurs (Half-Duplex mode). + This parameter can be a value of @ref ETH_Retry_Transmission */ + + uint32_t AutomaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping. + This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ + + uint32_t BackOffLimit; /*!< Selects the BackOff limit value. + This parameter can be a value of @ref ETH_Back_Off_Limit */ + + uint32_t DeferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode). + This parameter can be a value of @ref ETH_Deferral_Check */ + + uint32_t ReceiveAll; /*!< Selects or not all frames reception by the MAC (No filtering). + This parameter can be a value of @ref ETH_Receive_All */ + + uint32_t SourceAddrFilter; /*!< Selects the Source Address Filter mode. + This parameter can be a value of @ref ETH_Source_Addr_Filter */ + + uint32_t PassControlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) + This parameter can be a value of @ref ETH_Pass_Control_Frames */ + + uint32_t BroadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames. + This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ + + uint32_t DestinationAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames. + This parameter can be a value of @ref ETH_Destination_Addr_Filter */ + + uint32_t PromiscuousMode; /*!< Selects or not the Promiscuous Mode + This parameter can be a value of @ref ETH_Promiscuous_Mode */ + + uint32_t MulticastFramesFilter; /*!< Selects the Multicast Frames filter mode: None/HashTableFilter/PerfectFilter/PerfectHashTableFilter. + This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ + + uint32_t UnicastFramesFilter; /*!< Selects the Unicast Frames filter mode: HashTableFilter/PerfectFilter/PerfectHashTableFilter. + This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ + + uint32_t HashTableHigh; /*!< This field holds the higher 32 bits of Hash table. + This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFFU */ + + uint32_t HashTableLow; /*!< This field holds the lower 32 bits of Hash table. + This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFFU */ + + uint32_t PauseTime; /*!< This field holds the value to be used in the Pause Time field in the transmit control frame. + This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFU */ + + uint32_t ZeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames. + This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ + + uint32_t PauseLowThreshold; /*!< This field configures the threshold of the PAUSE to be checked for + automatic retransmission of PAUSE Frame. + This parameter can be a value of @ref ETH_Pause_Low_Threshold */ + + uint32_t UnicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address). + This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ + + uint32_t ReceiveFlowControl; /*!< Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) + This parameter can be a value of @ref ETH_Receive_Flow_Control */ + + uint32_t TransmitFlowControl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) + This parameter can be a value of @ref ETH_Transmit_Flow_Control */ + + uint32_t VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering. + This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ + + uint32_t VLANTagIdentifier; /*!< Holds the VLAN tag identifier for receive frames */ + +} ETH_MACInitTypeDef; + +/** + * @brief ETH DMA Configuration Structure definition + */ + +typedef struct +{ + uint32_t DropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames. + This parameter can be a value of @ref ETH_Drop_TCP_IP_Checksum_Error_Frame */ + + uint32_t ReceiveStoreForward; /*!< Enables or disables the Receive store and forward mode. + This parameter can be a value of @ref ETH_Receive_Store_Forward */ + + uint32_t FlushReceivedFrame; /*!< Enables or disables the flushing of received frames. + This parameter can be a value of @ref ETH_Flush_Received_Frame */ + + uint32_t TransmitStoreForward; /*!< Enables or disables Transmit store and forward mode. + This parameter can be a value of @ref ETH_Transmit_Store_Forward */ + + uint32_t TransmitThresholdControl; /*!< Selects or not the Transmit Threshold Control. + This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ + + uint32_t ForwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames. + This parameter can be a value of @ref ETH_Forward_Error_Frames */ + + uint32_t ForwardUndersizedGoodFrames; /*!< Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error + and length less than 64 bytes) including pad-bytes and CRC) + This parameter can be a value of @ref ETH_Forward_Undersized_Good_Frames */ + + uint32_t ReceiveThresholdControl; /*!< Selects the threshold level of the Receive FIFO. + This parameter can be a value of @ref ETH_Receive_Threshold_Control */ + + uint32_t SecondFrameOperate; /*!< Selects or not the Operate on second frame mode, which allows the DMA to process a second + frame of Transmit data even before obtaining the status for the first frame. + This parameter can be a value of @ref ETH_Second_Frame_Operate */ + + uint32_t AddressAlignedBeats; /*!< Enables or disables the Address Aligned Beats. + This parameter can be a value of @ref ETH_Address_Aligned_Beats */ + + uint32_t FixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers. + This parameter can be a value of @ref ETH_Fixed_Burst */ + + uint32_t RxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction. + This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ + + uint32_t TxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction. + This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ + + uint32_t EnhancedDescriptorFormat; /*!< Enables the enhanced descriptor format. + This parameter can be a value of @ref ETH_DMA_Enhanced_descriptor_format */ + + uint32_t DescriptorSkipLength; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) + This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ + + uint32_t DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration. + This parameter can be a value of @ref ETH_DMA_Arbitration */ +} ETH_DMAInitTypeDef; + + +/** + * @brief ETH DMA Descriptors data structure definition + */ + +typedef struct +{ + __IO uint32_t Status; /*!< Status */ + + uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ + + uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ + + uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ + + /*!< Enhanced ETHERNET DMA PTP Descriptors */ + uint32_t ExtendedStatus; /*!< Extended status for PTP receive descriptor */ + + uint32_t Reserved1; /*!< Reserved */ + + uint32_t TimeStampLow; /*!< Time Stamp Low value for transmit and receive */ + + uint32_t TimeStampHigh; /*!< Time Stamp High value for transmit and receive */ + +} ETH_DMADescTypeDef; + +/** + * @brief Received Frame Informations structure definition + */ +typedef struct +{ + ETH_DMADescTypeDef *FSRxDesc; /*!< First Segment Rx Desc */ + + ETH_DMADescTypeDef *LSRxDesc; /*!< Last Segment Rx Desc */ + + uint32_t SegCount; /*!< Segment count */ + + uint32_t length; /*!< Frame length */ + + uint32_t buffer; /*!< Frame buffer */ + +} ETH_DMARxFrameInfos; + +/** + * @brief ETH Handle Structure definition + */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +typedef struct __ETH_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +{ + ETH_TypeDef *Instance; /*!< Register base address */ + + ETH_InitTypeDef Init; /*!< Ethernet Init Configuration */ + + uint32_t LinkStatus; /*!< Ethernet link status */ + + ETH_DMADescTypeDef *RxDesc; /*!< Rx descriptor to Get */ + + ETH_DMADescTypeDef *TxDesc; /*!< Tx descriptor to Set */ + + ETH_DMARxFrameInfos RxFrameInfos; /*!< last Rx frame infos */ + + __IO HAL_ETH_StateTypeDef State; /*!< ETH communication state */ + + HAL_LockTypeDef Lock; /*!< ETH Lock */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + void (* TxCpltCallback) ( struct __ETH_HandleTypeDef * heth); /*!< ETH Tx Complete Callback */ + void (* RxCpltCallback) ( struct __ETH_HandleTypeDef * heth); /*!< ETH Rx Complete Callback */ + void (* DMAErrorCallback) ( struct __ETH_HandleTypeDef * heth); /*!< DMA Error Callback */ + void (* MspInitCallback) ( struct __ETH_HandleTypeDef * heth); /*!< ETH Msp Init callback */ + void (* MspDeInitCallback) ( struct __ETH_HandleTypeDef * heth); /*!< ETH Msp DeInit callback */ + +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +} ETH_HandleTypeDef; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief HAL ETH Callback ID enumeration definition + */ +typedef enum +{ + HAL_ETH_MSPINIT_CB_ID = 0x00U, /*!< ETH MspInit callback ID */ + HAL_ETH_MSPDEINIT_CB_ID = 0x01U, /*!< ETH MspDeInit callback ID */ + HAL_ETH_TX_COMPLETE_CB_ID = 0x02U, /*!< ETH Tx Complete Callback ID */ + HAL_ETH_RX_COMPLETE_CB_ID = 0x03U, /*!< ETH Rx Complete Callback ID */ + HAL_ETH_DMA_ERROR_CB_ID = 0x04U, /*!< ETH DMA Error Callback ID */ + +}HAL_ETH_CallbackIDTypeDef; + +/** + * @brief HAL ETH Callback pointer definition + */ +typedef void (*pETH_CallbackTypeDef)(ETH_HandleTypeDef * heth); /*!< pointer to an ETH callback function */ + +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ETH_Exported_Constants ETH Exported Constants + * @{ + */ + +/** @defgroup ETH_Buffers_setting ETH Buffers setting + * @{ + */ +#define ETH_MAX_PACKET_SIZE 1524U /*!< ETH_HEADER + ETH_EXTRA + ETH_VLAN_TAG + ETH_MAX_ETH_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14U /*!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4U /*!< Ethernet CRC */ +#define ETH_EXTRA 2U /*!< Extra bytes in some cases */ +#define ETH_VLAN_TAG 4U /*!< optional 802.1q VLAN Tag */ +#define ETH_MIN_ETH_PAYLOAD 46U /*!< Minimum Ethernet payload size */ +#define ETH_MAX_ETH_PAYLOAD 1500U /*!< Maximum Ethernet payload size */ +#define ETH_JUMBO_FRAME_PAYLOAD 9000U /*!< Jumbo frame payload size */ + + /* Ethernet driver receive buffers are organized in a chained linked-list, when + an ethernet packet is received, the Rx-DMA will transfer the packet from RxFIFO + to the driver receive buffers memory. + + Depending on the size of the received ethernet packet and the size of + each ethernet driver receive buffer, the received packet can take one or more + ethernet driver receive buffer. + + In below are defined the size of one ethernet driver receive buffer ETH_RX_BUF_SIZE + and the total count of the driver receive buffers ETH_RXBUFNB. + + The configured value for ETH_RX_BUF_SIZE and ETH_RXBUFNB are only provided as + example, they can be reconfigured in the application layer to fit the application + needs */ + +/* Here we configure each Ethernet driver receive buffer to fit the Max size Ethernet + packet */ +#ifndef ETH_RX_BUF_SIZE + #define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/* 5 Ethernet driver receive buffers are used (in a chained linked list)*/ +#ifndef ETH_RXBUFNB + #define ETH_RXBUFNB 5U /* 5 Rx buffers of size ETH_RX_BUF_SIZE */ +#endif + + + /* Ethernet driver transmit buffers are organized in a chained linked-list, when + an ethernet packet is transmitted, Tx-DMA will transfer the packet from the + driver transmit buffers memory to the TxFIFO. + + Depending on the size of the Ethernet packet to be transmitted and the size of + each ethernet driver transmit buffer, the packet to be transmitted can take + one or more ethernet driver transmit buffer. + + In below are defined the size of one ethernet driver transmit buffer ETH_TX_BUF_SIZE + and the total count of the driver transmit buffers ETH_TXBUFNB. + + The configured value for ETH_TX_BUF_SIZE and ETH_TXBUFNB are only provided as + example, they can be reconfigured in the application layer to fit the application + needs */ + +/* Here we configure each Ethernet driver transmit buffer to fit the Max size Ethernet + packet */ +#ifndef ETH_TX_BUF_SIZE + #define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE +#endif + +/* 5 ethernet driver transmit buffers are used (in a chained linked list)*/ +#ifndef ETH_TXBUFNB + #define ETH_TXBUFNB 5U /* 5 Tx buffers of size ETH_TX_BUF_SIZE */ +#endif + + /** + * @} + */ + +/** @defgroup ETH_DMA_TX_Descriptor ETH DMA TX Descriptor + * @{ + */ + +/* + DMA Tx Descriptor + ----------------------------------------------------------------------------------------------- + TDES0 | OWN(31) | CTRL[30:26] | Reserved[25:24] | CTRL[23:20] | Reserved[19:17] | Status[16:0] | + ----------------------------------------------------------------------------------------------- + TDES1 | Reserved[31:29] | Buffer2 ByteCount[28:16] | Reserved[15:13] | Buffer1 ByteCount[12:0] | + ----------------------------------------------------------------------------------------------- + TDES2 | Buffer1 Address [31:0] | + ----------------------------------------------------------------------------------------------- + TDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | + ----------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of TDES0 register: DMA Tx descriptor status register + */ +#define ETH_DMATXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMATXDESC_IC 0x40000000U /*!< Interrupt on Completion */ +#define ETH_DMATXDESC_LS 0x20000000U /*!< Last Segment */ +#define ETH_DMATXDESC_FS 0x10000000U /*!< First Segment */ +#define ETH_DMATXDESC_DC 0x08000000U /*!< Disable CRC */ +#define ETH_DMATXDESC_DP 0x04000000U /*!< Disable Padding */ +#define ETH_DMATXDESC_TTSE 0x02000000U /*!< Transmit Time Stamp Enable */ +#define ETH_DMATXDESC_CIC 0x00C00000U /*!< Checksum Insertion Control: 4 cases */ +#define ETH_DMATXDESC_CIC_BYPASS 0x00000000U /*!< Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMATXDESC_CIC_IPV4HEADER 0x00400000U /*!< IPV4 header Checksum Insertion */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_SEGMENT 0x00800000U /*!< TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMATXDESC_CIC_TCPUDPICMP_FULL 0x00C00000U /*!< TCP/UDP/ICMP Checksum Insertion fully calculated */ +#define ETH_DMATXDESC_TER 0x00200000U /*!< Transmit End of Ring */ +#define ETH_DMATXDESC_TCH 0x00100000U /*!< Second Address Chained */ +#define ETH_DMATXDESC_TTSS 0x00020000U /*!< Tx Time Stamp Status */ +#define ETH_DMATXDESC_IHE 0x00010000U /*!< IP Header Error */ +#define ETH_DMATXDESC_ES 0x00008000U /*!< Error summary: OR of the following bits: UE || ED || EC || LCO || NC || LCA || FF || JT */ +#define ETH_DMATXDESC_JT 0x00004000U /*!< Jabber Timeout */ +#define ETH_DMATXDESC_FF 0x00002000U /*!< Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMATXDESC_PCE 0x00001000U /*!< Payload Checksum Error */ +#define ETH_DMATXDESC_LCA 0x00000800U /*!< Loss of Carrier: carrier lost during transmission */ +#define ETH_DMATXDESC_NC 0x00000400U /*!< No Carrier: no carrier signal from the transceiver */ +#define ETH_DMATXDESC_LCO 0x00000200U /*!< Late Collision: transmission aborted due to collision */ +#define ETH_DMATXDESC_EC 0x00000100U /*!< Excessive Collision: transmission aborted after 16 collisions */ +#define ETH_DMATXDESC_VF 0x00000080U /*!< VLAN Frame */ +#define ETH_DMATXDESC_CC 0x00000078U /*!< Collision Count */ +#define ETH_DMATXDESC_ED 0x00000004U /*!< Excessive Deferral */ +#define ETH_DMATXDESC_UF 0x00000002U /*!< Underflow Error: late data arrival from the memory */ +#define ETH_DMATXDESC_DB 0x00000001U /*!< Deferred Bit */ + +/** + * @brief Bit definition of TDES1 register + */ +#define ETH_DMATXDESC_TBS2 0x1FFF0000U /*!< Transmit Buffer2 Size */ +#define ETH_DMATXDESC_TBS1 0x00001FFFU /*!< Transmit Buffer1 Size */ + +/** + * @brief Bit definition of TDES2 register + */ +#define ETH_DMATXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of TDES3 register + */ +#define ETH_DMATXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + + /*--------------------------------------------------------------------------------------------- + TDES6 | Transmit Time Stamp Low [31:0] | + ----------------------------------------------------------------------------------------------- + TDES7 | Transmit Time Stamp High [31:0] | + ----------------------------------------------------------------------------------------------*/ + +/* Bit definition of TDES6 register */ + #define ETH_DMAPTPTXDESC_TTSL 0xFFFFFFFFU /* Transmit Time Stamp Low */ + +/* Bit definition of TDES7 register */ + #define ETH_DMAPTPTXDESC_TTSH 0xFFFFFFFFU /* Transmit Time Stamp High */ + +/** + * @} + */ +/** @defgroup ETH_DMA_RX_Descriptor ETH DMA RX Descriptor + * @{ + */ + +/* + DMA Rx Descriptor + -------------------------------------------------------------------------------------------------------------------- + RDES0 | OWN(31) | Status [30:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES1 | CTRL(31) | Reserved[30:29] | Buffer2 ByteCount[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 ByteCount[12:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES2 | Buffer1 Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES3 | Buffer2 Address [31:0] / Next Descriptor Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- +*/ + +/** + * @brief Bit definition of RDES0 register: DMA Rx descriptor status register + */ +#define ETH_DMARXDESC_OWN 0x80000000U /*!< OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMARXDESC_AFM 0x40000000U /*!< DA Filter Fail for the rx frame */ +#define ETH_DMARXDESC_FL 0x3FFF0000U /*!< Receive descriptor frame length */ +#define ETH_DMARXDESC_ES 0x00008000U /*!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMARXDESC_DE 0x00004000U /*!< Descriptor error: no more descriptors for receive frame */ +#define ETH_DMARXDESC_SAF 0x00002000U /*!< SA Filter Fail for the received frame */ +#define ETH_DMARXDESC_LE 0x00001000U /*!< Frame size not matching with length field */ +#define ETH_DMARXDESC_OE 0x00000800U /*!< Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMARXDESC_VLAN 0x00000400U /*!< VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMARXDESC_FS 0x00000200U /*!< First descriptor of the frame */ +#define ETH_DMARXDESC_LS 0x00000100U /*!< Last descriptor of the frame */ +#define ETH_DMARXDESC_IPV4HCE 0x00000080U /*!< IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMARXDESC_LC 0x00000040U /*!< Late collision occurred during reception */ +#define ETH_DMARXDESC_FT 0x00000020U /*!< Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMARXDESC_RWT 0x00000010U /*!< Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMARXDESC_RE 0x00000008U /*!< Receive error: error reported by MII interface */ +#define ETH_DMARXDESC_DBE 0x00000004U /*!< Dribble bit error: frame contains non int multiple of 8 bits */ +#define ETH_DMARXDESC_CE 0x00000002U /*!< CRC error */ +#define ETH_DMARXDESC_MAMPCE 0x00000001U /*!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error */ + +/** + * @brief Bit definition of RDES1 register + */ +#define ETH_DMARXDESC_DIC 0x80000000U /*!< Disable Interrupt on Completion */ +#define ETH_DMARXDESC_RBS2 0x1FFF0000U /*!< Receive Buffer2 Size */ +#define ETH_DMARXDESC_RER 0x00008000U /*!< Receive End of Ring */ +#define ETH_DMARXDESC_RCH 0x00004000U /*!< Second Address Chained */ +#define ETH_DMARXDESC_RBS1 0x00001FFFU /*!< Receive Buffer1 Size */ + +/** + * @brief Bit definition of RDES2 register + */ +#define ETH_DMARXDESC_B1AP 0xFFFFFFFFU /*!< Buffer1 Address Pointer */ + +/** + * @brief Bit definition of RDES3 register + */ +#define ETH_DMARXDESC_B2AP 0xFFFFFFFFU /*!< Buffer2 Address Pointer */ + +/*--------------------------------------------------------------------------------------------------------------------- + RDES4 | Reserved[31:15] | Extended Status [14:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES5 | Reserved[31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES6 | Receive Time Stamp Low [31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES7 | Receive Time Stamp High [31:0] | + --------------------------------------------------------------------------------------------------------------------*/ + +/* Bit definition of RDES4 register */ +#define ETH_DMAPTPRXDESC_PTPV 0x00002000U /* PTP Version */ +#define ETH_DMAPTPRXDESC_PTPFT 0x00001000U /* PTP Frame Type */ +#define ETH_DMAPTPRXDESC_PTPMT 0x00000F00U /* PTP Message Type */ + #define ETH_DMAPTPRXDESC_PTPMT_SYNC 0x00000100U /* SYNC message (all clock types) */ + #define ETH_DMAPTPRXDESC_PTPMT_FOLLOWUP 0x00000200U /* FollowUp message (all clock types) */ + #define ETH_DMAPTPRXDESC_PTPMT_DELAYREQ 0x00000300U /* DelayReq message (all clock types) */ + #define ETH_DMAPTPRXDESC_PTPMT_DELAYRESP 0x00000400U /* DelayResp message (all clock types) */ + #define ETH_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE 0x00000500U /* PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock) */ + #define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG 0x00000600U /* PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock) */ + #define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U /* PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock) */ +#define ETH_DMAPTPRXDESC_IPV6PR 0x00000080U /* IPv6 Packet Received */ +#define ETH_DMAPTPRXDESC_IPV4PR 0x00000040U /* IPv4 Packet Received */ +#define ETH_DMAPTPRXDESC_IPCB 0x00000020U /* IP Checksum Bypassed */ +#define ETH_DMAPTPRXDESC_IPPE 0x00000010U /* IP Payload Error */ +#define ETH_DMAPTPRXDESC_IPHE 0x00000008U /* IP Header Error */ +#define ETH_DMAPTPRXDESC_IPPT 0x00000007U /* IP Payload Type */ + #define ETH_DMAPTPRXDESC_IPPT_UDP 0x00000001U /* UDP payload encapsulated in the IP datagram */ + #define ETH_DMAPTPRXDESC_IPPT_TCP 0x00000002U /* TCP payload encapsulated in the IP datagram */ + #define ETH_DMAPTPRXDESC_IPPT_ICMP 0x00000003U /* ICMP payload encapsulated in the IP datagram */ + +/* Bit definition of RDES6 register */ +#define ETH_DMAPTPRXDESC_RTSL 0xFFFFFFFFU /* Receive Time Stamp Low */ + +/* Bit definition of RDES7 register */ +#define ETH_DMAPTPRXDESC_RTSH 0xFFFFFFFFU /* Receive Time Stamp High */ +/** + * @} + */ + /** @defgroup ETH_AutoNegotiation ETH AutoNegotiation + * @{ + */ +#define ETH_AUTONEGOTIATION_ENABLE 0x00000001U +#define ETH_AUTONEGOTIATION_DISABLE 0x00000000U + +/** + * @} + */ +/** @defgroup ETH_Speed ETH Speed + * @{ + */ +#define ETH_SPEED_10M 0x00000000U +#define ETH_SPEED_100M 0x00004000U + +/** + * @} + */ +/** @defgroup ETH_Duplex_Mode ETH Duplex Mode + * @{ + */ +#define ETH_MODE_FULLDUPLEX 0x00000800U +#define ETH_MODE_HALFDUPLEX 0x00000000U +/** + * @} + */ +/** @defgroup ETH_Rx_Mode ETH Rx Mode + * @{ + */ +#define ETH_RXPOLLING_MODE 0x00000000U +#define ETH_RXINTERRUPT_MODE 0x00000001U +/** + * @} + */ + +/** @defgroup ETH_Checksum_Mode ETH Checksum Mode + * @{ + */ +#define ETH_CHECKSUM_BY_HARDWARE 0x00000000U +#define ETH_CHECKSUM_BY_SOFTWARE 0x00000001U +/** + * @} + */ + +/** @defgroup ETH_Media_Interface ETH Media Interface + * @{ + */ +#define ETH_MEDIA_INTERFACE_MII 0x00000000U +#define ETH_MEDIA_INTERFACE_RMII ((uint32_t)SYSCFG_PMC_MII_RMII_SEL) +/** + * @} + */ + +/** @defgroup ETH_Watchdog ETH Watchdog + * @{ + */ +#define ETH_WATCHDOG_ENABLE 0x00000000U +#define ETH_WATCHDOG_DISABLE 0x00800000U +/** + * @} + */ + +/** @defgroup ETH_Jabber ETH Jabber + * @{ + */ +#define ETH_JABBER_ENABLE 0x00000000U +#define ETH_JABBER_DISABLE 0x00400000U +/** + * @} + */ + +/** @defgroup ETH_Inter_Frame_Gap ETH Inter Frame Gap + * @{ + */ +#define ETH_INTERFRAMEGAP_96BIT 0x00000000U /*!< minimum IFG between frames during transmission is 96Bit */ +#define ETH_INTERFRAMEGAP_88BIT 0x00020000U /*!< minimum IFG between frames during transmission is 88Bit */ +#define ETH_INTERFRAMEGAP_80BIT 0x00040000U /*!< minimum IFG between frames during transmission is 80Bit */ +#define ETH_INTERFRAMEGAP_72BIT 0x00060000U /*!< minimum IFG between frames during transmission is 72Bit */ +#define ETH_INTERFRAMEGAP_64BIT 0x00080000U /*!< minimum IFG between frames during transmission is 64Bit */ +#define ETH_INTERFRAMEGAP_56BIT 0x000A0000U /*!< minimum IFG between frames during transmission is 56Bit */ +#define ETH_INTERFRAMEGAP_48BIT 0x000C0000U /*!< minimum IFG between frames during transmission is 48Bit */ +#define ETH_INTERFRAMEGAP_40BIT 0x000E0000U /*!< minimum IFG between frames during transmission is 40Bit */ +/** + * @} + */ + +/** @defgroup ETH_Carrier_Sense ETH Carrier Sense + * @{ + */ +#define ETH_CARRIERSENCE_ENABLE 0x00000000U +#define ETH_CARRIERSENCE_DISABLE 0x00010000U +/** + * @} + */ + +/** @defgroup ETH_Receive_Own ETH Receive Own + * @{ + */ +#define ETH_RECEIVEOWN_ENABLE 0x00000000U +#define ETH_RECEIVEOWN_DISABLE 0x00002000U +/** + * @} + */ + +/** @defgroup ETH_Loop_Back_Mode ETH Loop Back Mode + * @{ + */ +#define ETH_LOOPBACKMODE_ENABLE 0x00001000U +#define ETH_LOOPBACKMODE_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Checksum_Offload ETH Checksum Offload + * @{ + */ +#define ETH_CHECKSUMOFFLAOD_ENABLE 0x00000400U +#define ETH_CHECKSUMOFFLAOD_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Retry_Transmission ETH Retry Transmission + * @{ + */ +#define ETH_RETRYTRANSMISSION_ENABLE 0x00000000U +#define ETH_RETRYTRANSMISSION_DISABLE 0x00000200U +/** + * @} + */ + +/** @defgroup ETH_Automatic_Pad_CRC_Strip ETH Automatic Pad CRC Strip + * @{ + */ +#define ETH_AUTOMATICPADCRCSTRIP_ENABLE 0x00000080U +#define ETH_AUTOMATICPADCRCSTRIP_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Back_Off_Limit ETH Back Off Limit + * @{ + */ +#define ETH_BACKOFFLIMIT_10 0x00000000U +#define ETH_BACKOFFLIMIT_8 0x00000020U +#define ETH_BACKOFFLIMIT_4 0x00000040U +#define ETH_BACKOFFLIMIT_1 0x00000060U +/** + * @} + */ + +/** @defgroup ETH_Deferral_Check ETH Deferral Check + * @{ + */ +#define ETH_DEFFERRALCHECK_ENABLE 0x00000010U +#define ETH_DEFFERRALCHECK_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Receive_All ETH Receive All + * @{ + */ +#define ETH_RECEIVEALL_ENABLE 0x80000000U +#define ETH_RECEIVEAll_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Source_Addr_Filter ETH Source Addr Filter + * @{ + */ +#define ETH_SOURCEADDRFILTER_NORMAL_ENABLE 0x00000200U +#define ETH_SOURCEADDRFILTER_INVERSE_ENABLE 0x00000300U +#define ETH_SOURCEADDRFILTER_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Pass_Control_Frames ETH Pass Control Frames + * @{ + */ +#define ETH_PASSCONTROLFRAMES_BLOCKALL 0x00000040U /*!< MAC filters all control frames from reaching the application */ +#define ETH_PASSCONTROLFRAMES_FORWARDALL 0x00000080U /*!< MAC forwards all control frames to application even if they fail the Address Filter */ +#define ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER 0x000000C0U /*!< MAC forwards control frames that pass the Address Filter. */ +/** + * @} + */ + +/** @defgroup ETH_Broadcast_Frames_Reception ETH Broadcast Frames Reception + * @{ + */ +#define ETH_BROADCASTFRAMESRECEPTION_ENABLE 0x00000000U +#define ETH_BROADCASTFRAMESRECEPTION_DISABLE 0x00000020U +/** + * @} + */ + +/** @defgroup ETH_Destination_Addr_Filter ETH Destination Addr Filter + * @{ + */ +#define ETH_DESTINATIONADDRFILTER_NORMAL 0x00000000U +#define ETH_DESTINATIONADDRFILTER_INVERSE 0x00000008U +/** + * @} + */ + +/** @defgroup ETH_Promiscuous_Mode ETH Promiscuous Mode + * @{ + */ +#define ETH_PROMISCUOUS_MODE_ENABLE 0x00000001U +#define ETH_PROMISCUOUS_MODE_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Multicast_Frames_Filter ETH Multicast Frames Filter + * @{ + */ +#define ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE 0x00000404U +#define ETH_MULTICASTFRAMESFILTER_HASHTABLE 0x00000004U +#define ETH_MULTICASTFRAMESFILTER_PERFECT 0x00000000U +#define ETH_MULTICASTFRAMESFILTER_NONE 0x00000010U +/** + * @} + */ + +/** @defgroup ETH_Unicast_Frames_Filter ETH Unicast Frames Filter + * @{ + */ +#define ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE 0x00000402U +#define ETH_UNICASTFRAMESFILTER_HASHTABLE 0x00000002U +#define ETH_UNICASTFRAMESFILTER_PERFECT 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Zero_Quanta_Pause ETH Zero Quanta Pause + * @{ + */ +#define ETH_ZEROQUANTAPAUSE_ENABLE 0x00000000U +#define ETH_ZEROQUANTAPAUSE_DISABLE 0x00000080U +/** + * @} + */ + +/** @defgroup ETH_Pause_Low_Threshold ETH Pause Low Threshold + * @{ + */ +#define ETH_PAUSELOWTHRESHOLD_MINUS4 0x00000000U /*!< Pause time minus 4 slot times */ +#define ETH_PAUSELOWTHRESHOLD_MINUS28 0x00000010U /*!< Pause time minus 28 slot times */ +#define ETH_PAUSELOWTHRESHOLD_MINUS144 0x00000020U /*!< Pause time minus 144 slot times */ +#define ETH_PAUSELOWTHRESHOLD_MINUS256 0x00000030U /*!< Pause time minus 256 slot times */ +/** + * @} + */ + +/** @defgroup ETH_Unicast_Pause_Frame_Detect ETH Unicast Pause Frame Detect + * @{ + */ +#define ETH_UNICASTPAUSEFRAMEDETECT_ENABLE 0x00000008U +#define ETH_UNICASTPAUSEFRAMEDETECT_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Receive_Flow_Control ETH Receive Flow Control + * @{ + */ +#define ETH_RECEIVEFLOWCONTROL_ENABLE 0x00000004U +#define ETH_RECEIVEFLOWCONTROL_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Transmit_Flow_Control ETH Transmit Flow Control + * @{ + */ +#define ETH_TRANSMITFLOWCONTROL_ENABLE 0x00000002U +#define ETH_TRANSMITFLOWCONTROL_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_VLAN_Tag_Comparison ETH VLAN Tag Comparison + * @{ + */ +#define ETH_VLANTAGCOMPARISON_12BIT 0x00010000U +#define ETH_VLANTAGCOMPARISON_16BIT 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_MAC_addresses ETH MAC addresses + * @{ + */ +#define ETH_MAC_ADDRESS0 0x00000000U +#define ETH_MAC_ADDRESS1 0x00000008U +#define ETH_MAC_ADDRESS2 0x00000010U +#define ETH_MAC_ADDRESS3 0x00000018U +/** + * @} + */ + +/** @defgroup ETH_MAC_addresses_filter_SA_DA ETH MAC addresses filter SA DA + * @{ + */ +#define ETH_MAC_ADDRESSFILTER_SA 0x00000000U +#define ETH_MAC_ADDRESSFILTER_DA 0x00000008U +/** + * @} + */ + +/** @defgroup ETH_MAC_addresses_filter_Mask_bytes ETH MAC addresses filter Mask bytes + * @{ + */ +#define ETH_MAC_ADDRESSMASK_BYTE6 0x20000000U /*!< Mask MAC Address high reg bits [15:8] */ +#define ETH_MAC_ADDRESSMASK_BYTE5 0x10000000U /*!< Mask MAC Address high reg bits [7:0] */ +#define ETH_MAC_ADDRESSMASK_BYTE4 0x08000000U /*!< Mask MAC Address low reg bits [31:24] */ +#define ETH_MAC_ADDRESSMASK_BYTE3 0x04000000U /*!< Mask MAC Address low reg bits [23:16] */ +#define ETH_MAC_ADDRESSMASK_BYTE2 0x02000000U /*!< Mask MAC Address low reg bits [15:8] */ +#define ETH_MAC_ADDRESSMASK_BYTE1 0x01000000U /*!< Mask MAC Address low reg bits [70] */ +/** + * @} + */ + +/** @defgroup ETH_Drop_TCP_IP_Checksum_Error_Frame ETH Drop TCP IP Checksum Error Frame + * @{ + */ +#define ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE 0x00000000U +#define ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE 0x04000000U +/** + * @} + */ + +/** @defgroup ETH_Receive_Store_Forward ETH Receive Store Forward + * @{ + */ +#define ETH_RECEIVESTOREFORWARD_ENABLE 0x02000000U +#define ETH_RECEIVESTOREFORWARD_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Flush_Received_Frame ETH Flush Received Frame + * @{ + */ +#define ETH_FLUSHRECEIVEDFRAME_ENABLE 0x00000000U +#define ETH_FLUSHRECEIVEDFRAME_DISABLE 0x01000000U +/** + * @} + */ + +/** @defgroup ETH_Transmit_Store_Forward ETH Transmit Store Forward + * @{ + */ +#define ETH_TRANSMITSTOREFORWARD_ENABLE 0x00200000U +#define ETH_TRANSMITSTOREFORWARD_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Transmit_Threshold_Control ETH Transmit Threshold Control + * @{ + */ +#define ETH_TRANSMITTHRESHOLDCONTROL_64BYTES 0x00000000U /*!< threshold level of the MTL Transmit FIFO is 64 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_128BYTES 0x00004000U /*!< threshold level of the MTL Transmit FIFO is 128 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_192BYTES 0x00008000U /*!< threshold level of the MTL Transmit FIFO is 192 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_256BYTES 0x0000C000U /*!< threshold level of the MTL Transmit FIFO is 256 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_40BYTES 0x00010000U /*!< threshold level of the MTL Transmit FIFO is 40 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_32BYTES 0x00014000U /*!< threshold level of the MTL Transmit FIFO is 32 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_24BYTES 0x00018000U /*!< threshold level of the MTL Transmit FIFO is 24 Bytes */ +#define ETH_TRANSMITTHRESHOLDCONTROL_16BYTES 0x0001C000U /*!< threshold level of the MTL Transmit FIFO is 16 Bytes */ +/** + * @} + */ + +/** @defgroup ETH_Forward_Error_Frames ETH Forward Error Frames + * @{ + */ +#define ETH_FORWARDERRORFRAMES_ENABLE 0x00000080U +#define ETH_FORWARDERRORFRAMES_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Forward_Undersized_Good_Frames ETH Forward Undersized Good Frames + * @{ + */ +#define ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE 0x00000040U +#define ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Receive_Threshold_Control ETH Receive Threshold Control + * @{ + */ +#define ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES 0x00000000U /*!< threshold level of the MTL Receive FIFO is 64 Bytes */ +#define ETH_RECEIVEDTHRESHOLDCONTROL_32BYTES 0x00000008U /*!< threshold level of the MTL Receive FIFO is 32 Bytes */ +#define ETH_RECEIVEDTHRESHOLDCONTROL_96BYTES 0x00000010U /*!< threshold level of the MTL Receive FIFO is 96 Bytes */ +#define ETH_RECEIVEDTHRESHOLDCONTROL_128BYTES 0x00000018U /*!< threshold level of the MTL Receive FIFO is 128 Bytes */ +/** + * @} + */ + +/** @defgroup ETH_Second_Frame_Operate ETH Second Frame Operate + * @{ + */ +#define ETH_SECONDFRAMEOPERARTE_ENABLE 0x00000004U +#define ETH_SECONDFRAMEOPERARTE_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Address_Aligned_Beats ETH Address Aligned Beats + * @{ + */ +#define ETH_ADDRESSALIGNEDBEATS_ENABLE 0x02000000U +#define ETH_ADDRESSALIGNEDBEATS_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Fixed_Burst ETH Fixed Burst + * @{ + */ +#define ETH_FIXEDBURST_ENABLE 0x00010000U +#define ETH_FIXEDBURST_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_Rx_DMA_Burst_Length ETH Rx DMA Burst Length + * @{ + */ +#define ETH_RXDMABURSTLENGTH_1BEAT 0x00020000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 1 */ +#define ETH_RXDMABURSTLENGTH_2BEAT 0x00040000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 2 */ +#define ETH_RXDMABURSTLENGTH_4BEAT 0x00080000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RXDMABURSTLENGTH_8BEAT 0x00100000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RXDMABURSTLENGTH_16BEAT 0x00200000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RXDMABURSTLENGTH_32BEAT 0x00400000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_4BEAT 0x01020000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_8BEAT 0x01040000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_16BEAT 0x01080000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_32BEAT 0x01100000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_64BEAT 0x01200000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 64 */ +#define ETH_RXDMABURSTLENGTH_4XPBL_128BEAT 0x01400000U /*!< maximum number of beats to be transferred in one RxDMA transaction is 128 */ +/** + * @} + */ + +/** @defgroup ETH_Tx_DMA_Burst_Length ETH Tx DMA Burst Length + * @{ + */ +#define ETH_TXDMABURSTLENGTH_1BEAT 0x00000100U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ +#define ETH_TXDMABURSTLENGTH_2BEAT 0x00000200U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ +#define ETH_TXDMABURSTLENGTH_4BEAT 0x00000400U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TXDMABURSTLENGTH_8BEAT 0x00000800U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TXDMABURSTLENGTH_16BEAT 0x00001000U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TXDMABURSTLENGTH_32BEAT 0x00002000U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_4BEAT 0x01000100U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_8BEAT 0x01000200U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_16BEAT 0x01000400U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_32BEAT 0x01000800U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_64BEAT 0x01001000U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ +#define ETH_TXDMABURSTLENGTH_4XPBL_128BEAT 0x01002000U /*!< maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ +/** + * @} + */ + +/** @defgroup ETH_DMA_Enhanced_descriptor_format ETH DMA Enhanced descriptor format + * @{ + */ +#define ETH_DMAENHANCEDDESCRIPTOR_ENABLE 0x00000080U +#define ETH_DMAENHANCEDDESCRIPTOR_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETH_DMA_Arbitration ETH DMA Arbitration + * @{ + */ +#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1 0x00000000U +#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1 0x00004000U +#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1 0x00008000U +#define ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1 0x0000C000U +#define ETH_DMAARBITRATION_RXPRIORTX 0x00000002U +/** + * @} + */ + +/** @defgroup ETH_DMA_Tx_descriptor_segment ETH DMA Tx descriptor segment + * @{ + */ +#define ETH_DMATXDESC_LASTSEGMENTS 0x40000000U /*!< Last Segment */ +#define ETH_DMATXDESC_FIRSTSEGMENT 0x20000000U /*!< First Segment */ +/** + * @} + */ + +/** @defgroup ETH_DMA_Tx_descriptor_Checksum_Insertion_Control ETH DMA Tx descriptor Checksum Insertion Control + * @{ + */ +#define ETH_DMATXDESC_CHECKSUMBYPASS 0x00000000U /*!< Checksum engine bypass */ +#define ETH_DMATXDESC_CHECKSUMIPV4HEADER 0x00400000U /*!< IPv4 header checksum insertion */ +#define ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT 0x00800000U /*!< TCP/UDP/ICMP checksum insertion. Pseudo header checksum is assumed to be present */ +#define ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL 0x00C00000U /*!< TCP/UDP/ICMP checksum fully in hardware including pseudo header */ +/** + * @} + */ + +/** @defgroup ETH_DMA_Rx_descriptor_buffers ETH DMA Rx descriptor buffers + * @{ + */ +#define ETH_DMARXDESC_BUFFER1 0x00000000U /*!< DMA Rx Desc Buffer1 */ +#define ETH_DMARXDESC_BUFFER2 0x00000001U /*!< DMA Rx Desc Buffer2 */ +/** + * @} + */ + +/** @defgroup ETH_PMT_Flags ETH PMT Flags + * @{ + */ +#define ETH_PMT_FLAG_WUFFRPR 0x80000000U /*!< Wake-Up Frame Filter Register Pointer Reset */ +#define ETH_PMT_FLAG_WUFR 0x00000040U /*!< Wake-Up Frame Received */ +#define ETH_PMT_FLAG_MPR 0x00000020U /*!< Magic Packet Received */ +/** + * @} + */ + +/** @defgroup ETH_MMC_Tx_Interrupts ETH MMC Tx Interrupts + * @{ + */ +#define ETH_MMC_IT_TGF 0x00200000U /*!< When Tx good frame counter reaches half the maximum value */ +#define ETH_MMC_IT_TGFMSC 0x00008000U /*!< When Tx good multi col counter reaches half the maximum value */ +#define ETH_MMC_IT_TGFSC 0x00004000U /*!< When Tx good single col counter reaches half the maximum value */ +/** + * @} + */ + +/** @defgroup ETH_MMC_Rx_Interrupts ETH MMC Rx Interrupts + * @{ + */ +#define ETH_MMC_IT_RGUF 0x10020000U /*!< When Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMC_IT_RFAE 0x10000040U /*!< When Rx alignment error counter reaches half the maximum value */ +#define ETH_MMC_IT_RFCE 0x10000020U /*!< When Rx crc error counter reaches half the maximum value */ +/** + * @} + */ + +/** @defgroup ETH_MAC_Flags ETH MAC Flags + * @{ + */ +#define ETH_MAC_FLAG_TST 0x00000200U /*!< Time stamp trigger flag (on MAC) */ +#define ETH_MAC_FLAG_MMCT 0x00000040U /*!< MMC transmit flag */ +#define ETH_MAC_FLAG_MMCR 0x00000020U /*!< MMC receive flag */ +#define ETH_MAC_FLAG_MMC 0x00000010U /*!< MMC flag (on MAC) */ +#define ETH_MAC_FLAG_PMT 0x00000008U /*!< PMT flag (on MAC) */ +/** + * @} + */ + +/** @defgroup ETH_DMA_Flags ETH DMA Flags + * @{ + */ +#define ETH_DMA_FLAG_TST 0x20000000U /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_FLAG_PMT 0x10000000U /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_FLAG_MMC 0x08000000U /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_FLAG_DATATRANSFERERROR 0x00800000U /*!< Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMA_FLAG_READWRITEERROR 0x01000000U /*!< Error bits 0-write transfer, 1-read transfer */ +#define ETH_DMA_FLAG_ACCESSERROR 0x02000000U /*!< Error bits 0-data buffer, 1-desc. access */ +#define ETH_DMA_FLAG_NIS 0x00010000U /*!< Normal interrupt summary flag */ +#define ETH_DMA_FLAG_AIS 0x00008000U /*!< Abnormal interrupt summary flag */ +#define ETH_DMA_FLAG_ER 0x00004000U /*!< Early receive flag */ +#define ETH_DMA_FLAG_FBE 0x00002000U /*!< Fatal bus error flag */ +#define ETH_DMA_FLAG_ET 0x00000400U /*!< Early transmit flag */ +#define ETH_DMA_FLAG_RWT 0x00000200U /*!< Receive watchdog timeout flag */ +#define ETH_DMA_FLAG_RPS 0x00000100U /*!< Receive process stopped flag */ +#define ETH_DMA_FLAG_RBU 0x00000080U /*!< Receive buffer unavailable flag */ +#define ETH_DMA_FLAG_R 0x00000040U /*!< Receive flag */ +#define ETH_DMA_FLAG_TU 0x00000020U /*!< Underflow flag */ +#define ETH_DMA_FLAG_RO 0x00000010U /*!< Overflow flag */ +#define ETH_DMA_FLAG_TJT 0x00000008U /*!< Transmit jabber timeout flag */ +#define ETH_DMA_FLAG_TBU 0x00000004U /*!< Transmit buffer unavailable flag */ +#define ETH_DMA_FLAG_TPS 0x00000002U /*!< Transmit process stopped flag */ +#define ETH_DMA_FLAG_T 0x00000001U /*!< Transmit flag */ +/** + * @} + */ + +/** @defgroup ETH_MAC_Interrupts ETH MAC Interrupts + * @{ + */ +#define ETH_MAC_IT_TST 0x00000200U /*!< Time stamp trigger interrupt (on MAC) */ +#define ETH_MAC_IT_MMCT 0x00000040U /*!< MMC transmit interrupt */ +#define ETH_MAC_IT_MMCR 0x00000020U /*!< MMC receive interrupt */ +#define ETH_MAC_IT_MMC 0x00000010U /*!< MMC interrupt (on MAC) */ +#define ETH_MAC_IT_PMT 0x00000008U /*!< PMT interrupt (on MAC) */ +/** + * @} + */ + +/** @defgroup ETH_DMA_Interrupts ETH DMA Interrupts + * @{ + */ +#define ETH_DMA_IT_TST 0x20000000U /*!< Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_IT_PMT 0x10000000U /*!< PMT interrupt (on DMA) */ +#define ETH_DMA_IT_MMC 0x08000000U /*!< MMC interrupt (on DMA) */ +#define ETH_DMA_IT_NIS 0x00010000U /*!< Normal interrupt summary */ +#define ETH_DMA_IT_AIS 0x00008000U /*!< Abnormal interrupt summary */ +#define ETH_DMA_IT_ER 0x00004000U /*!< Early receive interrupt */ +#define ETH_DMA_IT_FBE 0x00002000U /*!< Fatal bus error interrupt */ +#define ETH_DMA_IT_ET 0x00000400U /*!< Early transmit interrupt */ +#define ETH_DMA_IT_RWT 0x00000200U /*!< Receive watchdog timeout interrupt */ +#define ETH_DMA_IT_RPS 0x00000100U /*!< Receive process stopped interrupt */ +#define ETH_DMA_IT_RBU 0x00000080U /*!< Receive buffer unavailable interrupt */ +#define ETH_DMA_IT_R 0x00000040U /*!< Receive interrupt */ +#define ETH_DMA_IT_TU 0x00000020U /*!< Underflow interrupt */ +#define ETH_DMA_IT_RO 0x00000010U /*!< Overflow interrupt */ +#define ETH_DMA_IT_TJT 0x00000008U /*!< Transmit jabber timeout interrupt */ +#define ETH_DMA_IT_TBU 0x00000004U /*!< Transmit buffer unavailable interrupt */ +#define ETH_DMA_IT_TPS 0x00000002U /*!< Transmit process stopped interrupt */ +#define ETH_DMA_IT_T 0x00000001U /*!< Transmit interrupt */ +/** + * @} + */ + +/** @defgroup ETH_DMA_transmit_process_state ETH DMA transmit process state + * @{ + */ +#define ETH_DMA_TRANSMITPROCESS_STOPPED 0x00000000U /*!< Stopped - Reset or Stop Tx Command issued */ +#define ETH_DMA_TRANSMITPROCESS_FETCHING 0x00100000U /*!< Running - fetching the Tx descriptor */ +#define ETH_DMA_TRANSMITPROCESS_WAITING 0x00200000U /*!< Running - waiting for status */ +#define ETH_DMA_TRANSMITPROCESS_READING 0x00300000U /*!< Running - reading the data from host memory */ +#define ETH_DMA_TRANSMITPROCESS_SUSPENDED 0x00600000U /*!< Suspended - Tx Descriptor unavailable */ +#define ETH_DMA_TRANSMITPROCESS_CLOSING 0x00700000U /*!< Running - closing Rx descriptor */ + +/** + * @} + */ + + +/** @defgroup ETH_DMA_receive_process_state ETH DMA receive process state + * @{ + */ +#define ETH_DMA_RECEIVEPROCESS_STOPPED 0x00000000U /*!< Stopped - Reset or Stop Rx Command issued */ +#define ETH_DMA_RECEIVEPROCESS_FETCHING 0x00020000U /*!< Running - fetching the Rx descriptor */ +#define ETH_DMA_RECEIVEPROCESS_WAITING 0x00060000U /*!< Running - waiting for packet */ +#define ETH_DMA_RECEIVEPROCESS_SUSPENDED 0x00080000U /*!< Suspended - Rx Descriptor unavailable */ +#define ETH_DMA_RECEIVEPROCESS_CLOSING 0x000A0000U /*!< Running - closing descriptor */ +#define ETH_DMA_RECEIVEPROCESS_QUEUING 0x000E0000U /*!< Running - queuing the receive frame into host memory */ + +/** + * @} + */ + +/** @defgroup ETH_DMA_overflow ETH DMA overflow + * @{ + */ +#define ETH_DMA_OVERFLOW_RXFIFOCOUNTER 0x10000000U /*!< Overflow bit for FIFO overflow counter */ +#define ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER 0x00010000U /*!< Overflow bit for missed frame counter */ +/** + * @} + */ + +/** @defgroup ETH_EXTI_LINE_WAKEUP ETH EXTI LINE WAKEUP + * @{ + */ +#define ETH_EXTI_LINE_WAKEUP 0x00080000U /*!< External interrupt line 19 Connected to the ETH EXTI Line */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup ETH_Exported_Macros ETH Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ + +/** @brief Reset ETH handle state + * @param __HANDLE__ specifies the ETH handle. + * @retval None + */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_ETH_STATE_RESET) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Checks whether the specified ETHERNET DMA Tx Desc flag is set or not. + * @param __HANDLE__ ETH Handle + * @param __FLAG__ specifies the flag of TDES0 to check. + * @retval the ETH_DMATxDescFlag (SET or RESET). + */ +#define __HAL_ETH_DMATXDESC_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->TxDesc->Status & (__FLAG__) == (__FLAG__)) + +/** + * @brief Checks whether the specified ETHERNET DMA Rx Desc flag is set or not. + * @param __HANDLE__ ETH Handle + * @param __FLAG__ specifies the flag of RDES0 to check. + * @retval the ETH_DMATxDescFlag (SET or RESET). + */ +#define __HAL_ETH_DMARXDESC_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->RxDesc->Status & (__FLAG__) == (__FLAG__)) + +/** + * @brief Enables the specified DMA Rx Desc receive interrupt. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMARXDESC_ENABLE_IT(__HANDLE__) ((__HANDLE__)->RxDesc->ControlBufferSize &=(~(uint32_t)ETH_DMARXDESC_DIC)) + +/** + * @brief Disables the specified DMA Rx Desc receive interrupt. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMARXDESC_DISABLE_IT(__HANDLE__) ((__HANDLE__)->RxDesc->ControlBufferSize |= ETH_DMARXDESC_DIC) + +/** + * @brief Set the specified DMA Rx Desc Own bit. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMARXDESC_SET_OWN_BIT(__HANDLE__) ((__HANDLE__)->RxDesc->Status |= ETH_DMARXDESC_OWN) + +/** + * @brief Returns the specified ETHERNET DMA Tx Desc collision count. + * @param __HANDLE__ ETH Handle + * @retval The Transmit descriptor collision counter value. + */ +#define __HAL_ETH_DMATXDESC_GET_COLLISION_COUNT(__HANDLE__) (((__HANDLE__)->TxDesc->Status & ETH_DMATXDESC_CC) >> ETH_DMATXDESC_COLLISION_COUNTSHIFT) + +/** + * @brief Set the specified DMA Tx Desc Own bit. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_SET_OWN_BIT(__HANDLE__) ((__HANDLE__)->TxDesc->Status |= ETH_DMATXDESC_OWN) + +/** + * @brief Enables the specified DMA Tx Desc Transmit interrupt. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_ENABLE_IT(__HANDLE__) ((__HANDLE__)->TxDesc->Status |= ETH_DMATXDESC_IC) + +/** + * @brief Disables the specified DMA Tx Desc Transmit interrupt. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_DISABLE_IT(__HANDLE__) ((__HANDLE__)->TxDesc->Status &= ~ETH_DMATXDESC_IC) + +/** + * @brief Selects the specified ETHERNET DMA Tx Desc Checksum Insertion. + * @param __HANDLE__ ETH Handle + * @param __CHECKSUM__ specifies is the DMA Tx desc checksum insertion. + * This parameter can be one of the following values: + * @arg ETH_DMATXDESC_CHECKSUMBYPASS : Checksum bypass + * @arg ETH_DMATXDESC_CHECKSUMIPV4HEADER : IPv4 header checksum + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT : TCP/UDP/ICMP checksum. Pseudo header checksum is assumed to be present + * @arg ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL : TCP/UDP/ICMP checksum fully in hardware including pseudo header + * @retval None + */ +#define __HAL_ETH_DMATXDESC_CHECKSUM_INSERTION(__HANDLE__, __CHECKSUM__) ((__HANDLE__)->TxDesc->Status |= (__CHECKSUM__)) + +/** + * @brief Enables the DMA Tx Desc CRC. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_CRC_ENABLE(__HANDLE__) ((__HANDLE__)->TxDesc->Status &= ~ETH_DMATXDESC_DC) + +/** + * @brief Disables the DMA Tx Desc CRC. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_CRC_DISABLE(__HANDLE__) ((__HANDLE__)->TxDesc->Status |= ETH_DMATXDESC_DC) + +/** + * @brief Enables the DMA Tx Desc padding for frame shorter than 64 bytes. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_SHORT_FRAME_PADDING_ENABLE(__HANDLE__) ((__HANDLE__)->TxDesc->Status &= ~ETH_DMATXDESC_DP) + +/** + * @brief Disables the DMA Tx Desc padding for frame shorter than 64 bytes. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_DMATXDESC_SHORT_FRAME_PADDING_DISABLE(__HANDLE__) ((__HANDLE__)->TxDesc->Status |= ETH_DMATXDESC_DP) + +/** + * @brief Enables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ ETH Handle + * @param __INTERRUPT__ specifies the ETHERNET MAC interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_MAC_IT_TST : Time stamp trigger interrupt + * @arg ETH_MAC_IT_PMT : PMT interrupt + * @retval None + */ +#define __HAL_ETH_MAC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIMR |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ ETH Handle + * @param __INTERRUPT__ specifies the ETHERNET MAC interrupt sources to be + * enabled or disabled. + * This parameter can be any combination of the following values: + * @arg ETH_MAC_IT_TST : Time stamp trigger interrupt + * @arg ETH_MAC_IT_PMT : PMT interrupt + * @retval None + */ +#define __HAL_ETH_MAC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIMR &= ~(__INTERRUPT__)) + +/** + * @brief Initiate a Pause Control Frame (Full-duplex only). + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_INITIATE_PAUSE_CONTROL_FRAME(__HANDLE__) ((__HANDLE__)->Instance->MACFCR |= ETH_MACFCR_FCBBPA) + +/** + * @brief Checks whether the ETHERNET flow control busy bit is set or not. + * @param __HANDLE__ ETH Handle + * @retval The new state of flow control busy status bit (SET or RESET). + */ +#define __HAL_ETH_GET_FLOW_CONTROL_BUSY_STATUS(__HANDLE__) (((__HANDLE__)->Instance->MACFCR & ETH_MACFCR_FCBBPA) == ETH_MACFCR_FCBBPA) + +/** + * @brief Enables the MAC Back Pressure operation activation (Half-duplex only). + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_BACK_PRESSURE_ACTIVATION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MACFCR |= ETH_MACFCR_FCBBPA) + +/** + * @brief Disables the MAC BackPressure operation activation (Half-duplex only). + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_BACK_PRESSURE_ACTIVATION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MACFCR &= ~ETH_MACFCR_FCBBPA) + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__ ETH Handle + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_MAC_FLAG_TST : Time stamp trigger flag + * @arg ETH_MAC_FLAG_MMCT : MMC transmit flag + * @arg ETH_MAC_FLAG_MMCR : MMC receive flag + * @arg ETH_MAC_FLAG_MMC : MMC flag + * @arg ETH_MAC_FLAG_PMT : PMT flag + * @retval The state of ETHERNET MAC flag. + */ +#define __HAL_ETH_MAC_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->MACSR &( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ ETH Handle + * @param __INTERRUPT__ specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ ETH Handle + * @param __INTERRUPT__ specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER &= ~(__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ ETH Handle + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMASR =(__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. +* @param __HANDLE__ ETH Handle + * @param __FLAG__ specifies the flag to check. @ref ETH_DMA_Flags + * @retval The new state of ETH_DMA_FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMASR &( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__ ETH Handle + * @param __FLAG__ specifies the flag to clear. @ref ETH_DMA_Flags + * @retval The new state of ETH_DMA_FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMASR = (__FLAG__)) + +/** + * @brief Checks whether the specified ETHERNET DMA overflow flag is set or not. + * @param __HANDLE__ ETH Handle + * @param __OVERFLOW__ specifies the DMA overflow flag to check. + * This parameter can be one of the following values: + * @arg ETH_DMA_OVERFLOW_RXFIFOCOUNTER : Overflow for FIFO Overflows Counter + * @arg ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER : Overflow for Buffer Unavailable Missed Frame Counter + * @retval The state of ETHERNET DMA overflow Flag (SET or RESET). + */ +#define __HAL_ETH_GET_DMA_OVERFLOW_STATUS(__HANDLE__, __OVERFLOW__) (((__HANDLE__)->Instance->DMAMFBOCR & (__OVERFLOW__)) == (__OVERFLOW__)) + +/** + * @brief Set the DMA Receive status watchdog timer register value + * @param __HANDLE__ ETH Handle + * @param __VALUE__ DMA Receive status watchdog timer register value + * @retval None + */ +#define __HAL_ETH_SET_RECEIVE_WATCHDOG_TIMER(__HANDLE__, __VALUE__) ((__HANDLE__)->Instance->DMARSWTR = (__VALUE__)) + +/** + * @brief Enables any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_GLOBAL_UNICAST_WAKEUP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR |= ETH_MACPMTCSR_GU) + +/** + * @brief Disables any unicast packet filtered by the MAC address + * recognition to be a wake-up frame. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_GLOBAL_UNICAST_WAKEUP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR &= ~ETH_MACPMTCSR_GU) + +/** + * @brief Enables the MAC Wake-Up Frame Detection. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_WAKEUP_FRAME_DETECTION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR |= ETH_MACPMTCSR_WFE) + +/** + * @brief Disables the MAC Wake-Up Frame Detection. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_WAKEUP_FRAME_DETECTION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR &= ~ETH_MACPMTCSR_WFE) + +/** + * @brief Enables the MAC Magic Packet Detection. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MAGIC_PACKET_DETECTION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR |= ETH_MACPMTCSR_MPE) + +/** + * @brief Disables the MAC Magic Packet Detection. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MAGIC_PACKET_DETECTION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR &= ~ETH_MACPMTCSR_WFE) + +/** + * @brief Enables the MAC Power Down. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_POWER_DOWN_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR |= ETH_MACPMTCSR_PD) + +/** + * @brief Disables the MAC Power Down. + * @param __HANDLE__ ETH Handle + * @retval None + */ +#define __HAL_ETH_POWER_DOWN_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MACPMTCSR &= ~ETH_MACPMTCSR_PD) + +/** + * @brief Checks whether the specified ETHERNET PMT flag is set or not. + * @param __HANDLE__ ETH Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg ETH_PMT_FLAG_WUFFRPR : Wake-Up Frame Filter Register Pointer Reset + * @arg ETH_PMT_FLAG_WUFR : Wake-Up Frame Received + * @arg ETH_PMT_FLAG_MPR : Magic Packet Received + * @retval The new state of ETHERNET PMT Flag (SET or RESET). + */ +#define __HAL_ETH_GET_PMT_FLAG_STATUS(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->MACPMTCSR &( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Preset and Initialize the MMC counters to almost-full value: 0xFFFF_FFF0 (full - 16) + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MMC_COUNTER_FULL_PRESET(__HANDLE__) ((__HANDLE__)->Instance->MMCCR |= (ETH_MMCCR_MCFHP | ETH_MMCCR_MCP)) + +/** + * @brief Preset and Initialize the MMC counters to almost-half value: 0x7FFF_FFF0 (half - 16) + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MMC_COUNTER_HALF_PRESET(__HANDLE__) do{(__HANDLE__)->Instance->MMCCR &= ~ETH_MMCCR_MCFHP;\ + (__HANDLE__)->Instance->MMCCR |= ETH_MMCCR_MCP;} while (0) + +/** + * @brief Enables the MMC Counter Freeze. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MMC_COUNTER_FREEZE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR |= ETH_MMCCR_MCF) + +/** + * @brief Disables the MMC Counter Freeze. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MMC_COUNTER_FREEZE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR &= ~ETH_MMCCR_MCF) + +/** + * @brief Enables the MMC Reset On Read. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_ETH_MMC_RESET_ONREAD_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR |= ETH_MMCCR_ROR) + +/** + * @brief Disables the MMC Reset On Read. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_ETH_MMC_RESET_ONREAD_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR &= ~ETH_MMCCR_ROR) + +/** + * @brief Enables the MMC Counter Stop Rollover. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_ETH_MMC_COUNTER_ROLLOVER_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR &= ~ETH_MMCCR_CSR) + +/** + * @brief Disables the MMC Counter Stop Rollover. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_ETH_MMC_COUNTER_ROLLOVER_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->MMCCR |= ETH_MMCCR_CSR) + +/** + * @brief Resets the MMC Counters. + * @param __HANDLE__ ETH Handle. + * @retval None + */ +#define __HAL_ETH_MMC_COUNTERS_RESET(__HANDLE__) ((__HANDLE__)->Instance->MMCCR |= ETH_MMCCR_CR) + +/** + * @brief Enables the specified ETHERNET MMC Rx interrupts. + * @param __HANDLE__ ETH Handle. + * @param __INTERRUPT__ specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_IT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_IT_RFCE : When Rx crc error counter reaches half the maximum value + * @retval None + */ +#define __HAL_ETH_MMC_RX_IT_ENABLE(__HANDLE__, __INTERRUPT__) (__HANDLE__)->Instance->MMCRIMR &= ~((__INTERRUPT__) & 0xEFFFFFFFU) +/** + * @brief Disables the specified ETHERNET MMC Rx interrupts. + * @param __HANDLE__ ETH Handle. + * @param __INTERRUPT__ specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_RGUF : When Rx good unicast frames counter reaches half the maximum value + * @arg ETH_MMC_IT_RFAE : When Rx alignment error counter reaches half the maximum value + * @arg ETH_MMC_IT_RFCE : When Rx crc error counter reaches half the maximum value + * @retval None + */ +#define __HAL_ETH_MMC_RX_IT_DISABLE(__HANDLE__, __INTERRUPT__) (__HANDLE__)->Instance->MMCRIMR |= ((__INTERRUPT__) & 0xEFFFFFFFU) +/** + * @brief Enables the specified ETHERNET MMC Tx interrupts. + * @param __HANDLE__ ETH Handle. + * @param __INTERRUPT__ specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_IT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_IT_TGFSC : When Tx good single col counter reaches half the maximum value + * @retval None + */ +#define __HAL_ETH_MMC_TX_IT_ENABLE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MMCRIMR &= ~ (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET MMC Tx interrupts. + * @param __HANDLE__ ETH Handle. + * @param __INTERRUPT__ specifies the ETHERNET MMC interrupt sources to be enabled or disabled. + * This parameter can be one of the following values: + * @arg ETH_MMC_IT_TGF : When Tx good frame counter reaches half the maximum value + * @arg ETH_MMC_IT_TGFMSC: When Tx good multi col counter reaches half the maximum value + * @arg ETH_MMC_IT_TGFSC : When Tx good single col counter reaches half the maximum value + * @retval None + */ +#define __HAL_ETH_MMC_TX_IT_DISABLE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MMCRIMR |= (__INTERRUPT__)) + +/** + * @brief Enables the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT() EXTI->IMR |= (ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Disables the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_DISABLE_IT() EXTI->IMR &= ~(ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Enable event on ETH External event line. + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_EVENT() EXTI->EMR |= (ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Disable event on ETH External event line + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_DISABLE_EVENT() EXTI->EMR &= ~(ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Get flag of the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG() EXTI->PR & (ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Clear flag of the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG() EXTI->PR = (ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Enables rising edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE_TRIGGER() EXTI->RTSR |= ETH_EXTI_LINE_WAKEUP + +/** + * @brief Disables the rising edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_DISABLE_RISING_EDGE_TRIGGER() EXTI->RTSR &= ~(ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Enables falling edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE_TRIGGER() EXTI->FTSR |= (ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Disables falling edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_DISABLE_FALLING_EDGE_TRIGGER() EXTI->FTSR &= ~(ETH_EXTI_LINE_WAKEUP) + +/** + * @brief Enables rising/falling edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLINGRISING_TRIGGER() do{EXTI->RTSR |= ETH_EXTI_LINE_WAKEUP;\ + EXTI->FTSR |= ETH_EXTI_LINE_WAKEUP;\ + }while(0U) + +/** + * @brief Disables rising/falling edge trigger to the ETH External interrupt line. + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_DISABLE_FALLINGRISING_TRIGGER() do{EXTI->RTSR &= ~(ETH_EXTI_LINE_WAKEUP);\ + EXTI->FTSR &= ~(ETH_EXTI_LINE_WAKEUP);\ + }while(0U) + +/** + * @brief Generate a Software interrupt on selected EXTI line. + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT() EXTI->SWIER|= ETH_EXTI_LINE_WAKEUP + +/** + * @} + */ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DMATxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMATxDescTab, uint8_t* TxBuff, uint32_t TxBuffCount); +HAL_StatusTypeDef HAL_ETH_DMARxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount); +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ +/* IO operation functions ****************************************************/ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength); +HAL_StatusTypeDef HAL_ETH_GetReceivedFrame(ETH_HandleTypeDef *heth); +/* Communication with PHY functions*/ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t *RegValue); +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t RegValue); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_ETH_GetReceivedFrame_IT(ETH_HandleTypeDef *heth); +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +/* Callback in non blocking modes (Interrupt) */ +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ + +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef *dmaconf); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx ||\ + STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_ETH_LEGACY_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h new file mode 100644 index 0000000..3ae73f0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32_assert_template.h @@ -0,0 +1,56 @@ +/** + ****************************************************************************** + * @file stm32_assert.h + * @author MCD Application Team + * @brief STM32 assert template file. + * This file should be copied to the application folder and renamed + * to stm32_assert.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32_ASSERT_H +#define __STM32_ASSERT_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Includes ------------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32_ASSERT_H */ + + + diff --git a/libs/hal/stm32f4xx_hal.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h similarity index 100% rename from libs/hal/stm32f4xx_hal.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h new file mode 100644 index 0000000..c79a073 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc.h @@ -0,0 +1,898 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_adc.h + * @author MCD Application Team + * @brief Header file containing functions prototypes of ADC HAL library. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_ADC_H +#define __STM32F4xx_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/* Include low level driver */ +#include "stm32f4xx_ll_adc.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup ADC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup ADC_Exported_Types ADC Exported Types + * @{ + */ + +/** + * @brief Structure definition of ADC and regular group initialization + * @note Parameters of this structure are shared within 2 scopes: + * - Scope entire ADC (affects regular and injected groups): ClockPrescaler, Resolution, ScanConvMode, DataAlign, ScanConvMode, EOCSelection, LowPowerAutoWait, LowPowerAutoPowerOff, ChannelsBank. + * - Scope regular group: ContinuousConvMode, NbrOfConversion, DiscontinuousConvMode, NbrOfDiscConversion, ExternalTrigConvEdge, ExternalTrigConv. + * @note The setting of these parameters with function HAL_ADC_Init() is conditioned to ADC state. + * ADC state can be either: + * - For all parameters: ADC disabled + * - For all parameters except 'Resolution', 'ScanConvMode', 'DiscontinuousConvMode', 'NbrOfDiscConversion' : ADC enabled without conversion on going on regular group. + * - For parameters 'ExternalTrigConv' and 'ExternalTrigConvEdge': ADC enabled, even with conversion on going. + * If ADC is not in the appropriate state to modify some parameters, these parameters setting is bypassed + * without error reporting (as it can be the expected behaviour in case of intended action to update another parameter (which fulfills the ADC state condition) on the fly). + */ +typedef struct +{ + uint32_t ClockPrescaler; /*!< Select ADC clock prescaler. The clock is common for + all the ADCs. + This parameter can be a value of @ref ADC_ClockPrescaler */ + uint32_t Resolution; /*!< Configures the ADC resolution. + This parameter can be a value of @ref ADC_Resolution */ + uint32_t DataAlign; /*!< Specifies ADC data alignment to right (MSB on register bit 11 and LSB on register bit 0) (default setting) + or to left (if regular group: MSB on register bit 15 and LSB on register bit 4, if injected group (MSB kept as signed value due to potential negative value after offset application): MSB on register bit 14 and LSB on register bit 3). + This parameter can be a value of @ref ADC_Data_align */ + uint32_t ScanConvMode; /*!< Configures the sequencer of regular and injected groups. + This parameter can be associated to parameter 'DiscontinuousConvMode' to have main sequence subdivided in successive parts. + If disabled: Conversion is performed in single mode (one channel converted, the one defined in rank 1). + Parameters 'NbrOfConversion' and 'InjectedNbrOfConversion' are discarded (equivalent to set to 1). + If enabled: Conversions are performed in sequence mode (multiple ranks defined by 'NbrOfConversion'/'InjectedNbrOfConversion' and each channel rank). + Scan direction is upward: from rank1 to rank 'n'. + This parameter can be set to ENABLE or DISABLE */ + uint32_t EOCSelection; /*!< Specifies what EOC (End Of Conversion) flag is used for conversion by polling and interruption: end of conversion of each rank or complete sequence. + This parameter can be a value of @ref ADC_EOCSelection. + Note: For injected group, end of conversion (flag&IT) is raised only at the end of the sequence. + Therefore, if end of conversion is set to end of each conversion, injected group should not be used with interruption (HAL_ADCEx_InjectedStart_IT) + or polling (HAL_ADCEx_InjectedStart and HAL_ADCEx_InjectedPollForConversion). By the way, polling is still possible since driver will use an estimated timing for end of injected conversion. + Note: If overrun feature is intended to be used, use ADC in mode 'interruption' (function HAL_ADC_Start_IT() ) with parameter EOCSelection set to end of each conversion or in mode 'transfer by DMA' (function HAL_ADC_Start_DMA()). + If overrun feature is intended to be bypassed, use ADC in mode 'polling' or 'interruption' with parameter EOCSelection must be set to end of sequence */ + FunctionalState ContinuousConvMode; /*!< Specifies whether the conversion is performed in single mode (one conversion) or continuous mode for regular group, + after the selected trigger occurred (software start or external trigger). + This parameter can be set to ENABLE or DISABLE. */ + uint32_t NbrOfConversion; /*!< Specifies the number of ranks that will be converted within the regular group sequencer. + To use regular group sequencer and convert several ranks, parameter 'ScanConvMode' must be enabled. + This parameter must be a number between Min_Data = 1 and Max_Data = 16. */ + FunctionalState DiscontinuousConvMode; /*!< Specifies whether the conversions sequence of regular group is performed in Complete-sequence/Discontinuous-sequence (main sequence subdivided in successive parts). + Discontinuous mode is used only if sequencer is enabled (parameter 'ScanConvMode'). If sequencer is disabled, this parameter is discarded. + Discontinuous mode can be enabled only if continuous mode is disabled. If continuous mode is enabled, this parameter setting is discarded. + This parameter can be set to ENABLE or DISABLE. */ + uint32_t NbrOfDiscConversion; /*!< Specifies the number of discontinuous conversions in which the main sequence of regular group (parameter NbrOfConversion) will be subdivided. + If parameter 'DiscontinuousConvMode' is disabled, this parameter is discarded. + This parameter must be a number between Min_Data = 1 and Max_Data = 8. */ + uint32_t ExternalTrigConv; /*!< Selects the external event used to trigger the conversion start of regular group. + If set to ADC_SOFTWARE_START, external triggers are disabled. + If set to external trigger source, triggering is on event rising edge by default. + This parameter can be a value of @ref ADC_External_trigger_Source_Regular */ + uint32_t ExternalTrigConvEdge; /*!< Selects the external trigger edge of regular group. + If trigger is set to ADC_SOFTWARE_START, this parameter is discarded. + This parameter can be a value of @ref ADC_External_trigger_edge_Regular */ + FunctionalState DMAContinuousRequests; /*!< Specifies whether the DMA requests are performed in one shot mode (DMA transfer stop when number of conversions is reached) + or in Continuous mode (DMA transfer unlimited, whatever number of conversions). + Note: In continuous mode, DMA must be configured in circular mode. Otherwise an overrun will be triggered when DMA buffer maximum pointer is reached. + Note: This parameter must be modified when no conversion is on going on both regular and injected groups (ADC disabled, or ADC enabled without continuous mode or external trigger that could launch a conversion). + This parameter can be set to ENABLE or DISABLE. */ +} ADC_InitTypeDef; + + + +/** + * @brief Structure definition of ADC channel for regular group + * @note The setting of these parameters with function HAL_ADC_ConfigChannel() is conditioned to ADC state. + * ADC can be either disabled or enabled without conversion on going on regular group. + */ +typedef struct +{ + uint32_t Channel; /*!< Specifies the channel to configure into ADC regular group. + This parameter can be a value of @ref ADC_channels */ + uint32_t Rank; /*!< Specifies the rank in the regular group sequencer. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ + uint32_t SamplingTime; /*!< Sampling time value to be set for the selected channel. + Unit: ADC clock cycles + Conversion time is the addition of sampling time and processing time (12 ADC clock cycles at ADC resolution 12 bits, 11 cycles at 10 bits, 9 cycles at 8 bits, 7 cycles at 6 bits). + This parameter can be a value of @ref ADC_sampling_times + Caution: This parameter updates the parameter property of the channel, that can be used into regular and/or injected groups. + If this same channel has been previously configured in the other group (regular/injected), it will be updated to last setting. + Note: In case of usage of internal measurement channels (VrefInt/Vbat/TempSensor), + sampling time constraints must be respected (sampling time can be adjusted in function of ADC clock frequency and sampling time setting) + Refer to device datasheet for timings values, parameters TS_vrefint, TS_temp (values rough order: 4us min). */ + uint32_t Offset; /*!< Reserved for future use, can be set to 0 */ +} ADC_ChannelConfTypeDef; + +/** + * @brief ADC Configuration multi-mode structure definition + */ +typedef struct +{ + uint32_t WatchdogMode; /*!< Configures the ADC analog watchdog mode. + This parameter can be a value of @ref ADC_analog_watchdog_selection */ + uint32_t HighThreshold; /*!< Configures the ADC analog watchdog High threshold value. + This parameter must be a 12-bit value. */ + uint32_t LowThreshold; /*!< Configures the ADC analog watchdog High threshold value. + This parameter must be a 12-bit value. */ + uint32_t Channel; /*!< Configures ADC channel for the analog watchdog. + This parameter has an effect only if watchdog mode is configured on single channel + This parameter can be a value of @ref ADC_channels */ + FunctionalState ITMode; /*!< Specifies whether the analog watchdog is configured + is interrupt mode or in polling mode. + This parameter can be set to ENABLE or DISABLE */ + uint32_t WatchdogNumber; /*!< Reserved for future use, can be set to 0 */ +} ADC_AnalogWDGConfTypeDef; + +/** + * @brief HAL ADC state machine: ADC states definition (bitfields) + */ +/* States of ADC global scope */ +#define HAL_ADC_STATE_RESET 0x00000000U /*!< ADC not yet initialized or disabled */ +#define HAL_ADC_STATE_READY 0x00000001U /*!< ADC peripheral ready for use */ +#define HAL_ADC_STATE_BUSY_INTERNAL 0x00000002U /*!< ADC is busy to internal process (initialization, calibration) */ +#define HAL_ADC_STATE_TIMEOUT 0x00000004U /*!< TimeOut occurrence */ + +/* States of ADC errors */ +#define HAL_ADC_STATE_ERROR_INTERNAL 0x00000010U /*!< Internal error occurrence */ +#define HAL_ADC_STATE_ERROR_CONFIG 0x00000020U /*!< Configuration error occurrence */ +#define HAL_ADC_STATE_ERROR_DMA 0x00000040U /*!< DMA error occurrence */ + +/* States of ADC group regular */ +#define HAL_ADC_STATE_REG_BUSY 0x00000100U /*!< A conversion on group regular is ongoing or can occur (either by continuous mode, + external trigger, low power auto power-on (if feature available), multimode ADC master control (if feature available)) */ +#define HAL_ADC_STATE_REG_EOC 0x00000200U /*!< Conversion data available on group regular */ +#define HAL_ADC_STATE_REG_OVR 0x00000400U /*!< Overrun occurrence */ + +/* States of ADC group injected */ +#define HAL_ADC_STATE_INJ_BUSY 0x00001000U /*!< A conversion on group injected is ongoing or can occur (either by auto-injection mode, + external trigger, low power auto power-on (if feature available), multimode ADC master control (if feature available)) */ +#define HAL_ADC_STATE_INJ_EOC 0x00002000U /*!< Conversion data available on group injected */ + +/* States of ADC analog watchdogs */ +#define HAL_ADC_STATE_AWD1 0x00010000U /*!< Out-of-window occurrence of analog watchdog 1 */ +#define HAL_ADC_STATE_AWD2 0x00020000U /*!< Not available on STM32F4 device: Out-of-window occurrence of analog watchdog 2 */ +#define HAL_ADC_STATE_AWD3 0x00040000U /*!< Not available on STM32F4 device: Out-of-window occurrence of analog watchdog 3 */ + +/* States of ADC multi-mode */ +#define HAL_ADC_STATE_MULTIMODE_SLAVE 0x00100000U /*!< Not available on STM32F4 device: ADC in multimode slave state, controlled by another ADC master ( */ + + +/** + * @brief ADC handle Structure definition + */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +typedef struct __ADC_HandleTypeDef +#else +typedef struct +#endif +{ + ADC_TypeDef *Instance; /*!< Register base address */ + + ADC_InitTypeDef Init; /*!< ADC required parameters */ + + __IO uint32_t NbrOfCurrentConversionRank; /*!< ADC number of current conversion rank */ + + DMA_HandleTypeDef *DMA_Handle; /*!< Pointer DMA Handler */ + + HAL_LockTypeDef Lock; /*!< ADC locking object */ + + __IO uint32_t State; /*!< ADC communication state */ + + __IO uint32_t ErrorCode; /*!< ADC Error code */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + void (* ConvCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC conversion complete callback */ + void (* ConvHalfCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC conversion DMA half-transfer callback */ + void (* LevelOutOfWindowCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC analog watchdog 1 callback */ + void (* ErrorCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC error callback */ + void (* InjectedConvCpltCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC group injected conversion complete callback */ + void (* MspInitCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC Msp Init callback */ + void (* MspDeInitCallback)(struct __ADC_HandleTypeDef *hadc); /*!< ADC Msp DeInit callback */ +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ +} ADC_HandleTypeDef; + +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +/** + * @brief HAL ADC Callback ID enumeration definition + */ +typedef enum +{ + HAL_ADC_CONVERSION_COMPLETE_CB_ID = 0x00U, /*!< ADC conversion complete callback ID */ + HAL_ADC_CONVERSION_HALF_CB_ID = 0x01U, /*!< ADC conversion DMA half-transfer callback ID */ + HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID = 0x02U, /*!< ADC analog watchdog 1 callback ID */ + HAL_ADC_ERROR_CB_ID = 0x03U, /*!< ADC error callback ID */ + HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID = 0x04U, /*!< ADC group injected conversion complete callback ID */ + HAL_ADC_MSPINIT_CB_ID = 0x05U, /*!< ADC Msp Init callback ID */ + HAL_ADC_MSPDEINIT_CB_ID = 0x06U /*!< ADC Msp DeInit callback ID */ +} HAL_ADC_CallbackIDTypeDef; + +/** + * @brief HAL ADC Callback pointer definition + */ +typedef void (*pADC_CallbackTypeDef)(ADC_HandleTypeDef *hadc); /*!< pointer to a ADC callback function */ + +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ADC_Exported_Constants ADC Exported Constants + * @{ + */ + +/** @defgroup ADC_Error_Code ADC Error Code + * @{ + */ +#define HAL_ADC_ERROR_NONE 0x00U /*!< No error */ +#define HAL_ADC_ERROR_INTERNAL 0x01U /*!< ADC IP internal error: if problem of clocking, + enable/disable, erroneous state */ +#define HAL_ADC_ERROR_OVR 0x02U /*!< Overrun error */ +#define HAL_ADC_ERROR_DMA 0x04U /*!< DMA transfer error */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +#define HAL_ADC_ERROR_INVALID_CALLBACK (0x10U) /*!< Invalid Callback error */ +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ +/** + * @} + */ + + +/** @defgroup ADC_ClockPrescaler ADC Clock Prescaler + * @{ + */ +#define ADC_CLOCK_SYNC_PCLK_DIV2 0x00000000U +#define ADC_CLOCK_SYNC_PCLK_DIV4 ((uint32_t)ADC_CCR_ADCPRE_0) +#define ADC_CLOCK_SYNC_PCLK_DIV6 ((uint32_t)ADC_CCR_ADCPRE_1) +#define ADC_CLOCK_SYNC_PCLK_DIV8 ((uint32_t)ADC_CCR_ADCPRE) +/** + * @} + */ + +/** @defgroup ADC_delay_between_2_sampling_phases ADC Delay Between 2 Sampling Phases + * @{ + */ +#define ADC_TWOSAMPLINGDELAY_5CYCLES 0x00000000U +#define ADC_TWOSAMPLINGDELAY_6CYCLES ((uint32_t)ADC_CCR_DELAY_0) +#define ADC_TWOSAMPLINGDELAY_7CYCLES ((uint32_t)ADC_CCR_DELAY_1) +#define ADC_TWOSAMPLINGDELAY_8CYCLES ((uint32_t)(ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_9CYCLES ((uint32_t)ADC_CCR_DELAY_2) +#define ADC_TWOSAMPLINGDELAY_10CYCLES ((uint32_t)(ADC_CCR_DELAY_2 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_11CYCLES ((uint32_t)(ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1)) +#define ADC_TWOSAMPLINGDELAY_12CYCLES ((uint32_t)(ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_13CYCLES ((uint32_t)ADC_CCR_DELAY_3) +#define ADC_TWOSAMPLINGDELAY_14CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_15CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_1)) +#define ADC_TWOSAMPLINGDELAY_16CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_17CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2)) +#define ADC_TWOSAMPLINGDELAY_18CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 | ADC_CCR_DELAY_0)) +#define ADC_TWOSAMPLINGDELAY_19CYCLES ((uint32_t)(ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1)) +#define ADC_TWOSAMPLINGDELAY_20CYCLES ((uint32_t)ADC_CCR_DELAY) +/** + * @} + */ + +/** @defgroup ADC_Resolution ADC Resolution + * @{ + */ +#define ADC_RESOLUTION_12B 0x00000000U +#define ADC_RESOLUTION_10B ((uint32_t)ADC_CR1_RES_0) +#define ADC_RESOLUTION_8B ((uint32_t)ADC_CR1_RES_1) +#define ADC_RESOLUTION_6B ((uint32_t)ADC_CR1_RES) +/** + * @} + */ + +/** @defgroup ADC_External_trigger_edge_Regular ADC External Trigger Edge Regular + * @{ + */ +#define ADC_EXTERNALTRIGCONVEDGE_NONE 0x00000000U +#define ADC_EXTERNALTRIGCONVEDGE_RISING ((uint32_t)ADC_CR2_EXTEN_0) +#define ADC_EXTERNALTRIGCONVEDGE_FALLING ((uint32_t)ADC_CR2_EXTEN_1) +#define ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING ((uint32_t)ADC_CR2_EXTEN) +/** + * @} + */ + +/** @defgroup ADC_External_trigger_Source_Regular ADC External Trigger Source Regular + * @{ + */ +/* Note: Parameter ADC_SOFTWARE_START is a software parameter used for */ +/* compatibility with other STM32 devices. */ +#define ADC_EXTERNALTRIGCONV_T1_CC1 0x00000000U +#define ADC_EXTERNALTRIGCONV_T1_CC2 ((uint32_t)ADC_CR2_EXTSEL_0) +#define ADC_EXTERNALTRIGCONV_T1_CC3 ((uint32_t)ADC_CR2_EXTSEL_1) +#define ADC_EXTERNALTRIGCONV_T2_CC2 ((uint32_t)(ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T2_CC3 ((uint32_t)ADC_CR2_EXTSEL_2) +#define ADC_EXTERNALTRIGCONV_T2_CC4 ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T2_TRGO ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1)) +#define ADC_EXTERNALTRIGCONV_T3_CC1 ((uint32_t)(ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T3_TRGO ((uint32_t)ADC_CR2_EXTSEL_3) +#define ADC_EXTERNALTRIGCONV_T4_CC4 ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T5_CC1 ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1)) +#define ADC_EXTERNALTRIGCONV_T5_CC2 ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T5_CC3 ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2)) +#define ADC_EXTERNALTRIGCONV_T8_CC1 ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0)) +#define ADC_EXTERNALTRIGCONV_T8_TRGO ((uint32_t)(ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1)) +#define ADC_EXTERNALTRIGCONV_Ext_IT11 ((uint32_t)ADC_CR2_EXTSEL) +#define ADC_SOFTWARE_START ((uint32_t)ADC_CR2_EXTSEL + 1U) +/** + * @} + */ + +/** @defgroup ADC_Data_align ADC Data Align + * @{ + */ +#define ADC_DATAALIGN_RIGHT 0x00000000U +#define ADC_DATAALIGN_LEFT ((uint32_t)ADC_CR2_ALIGN) +/** + * @} + */ + +/** @defgroup ADC_channels ADC Common Channels + * @{ + */ +#define ADC_CHANNEL_0 0x00000000U +#define ADC_CHANNEL_1 ((uint32_t)ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_2 ((uint32_t)ADC_CR1_AWDCH_1) +#define ADC_CHANNEL_3 ((uint32_t)(ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_4 ((uint32_t)ADC_CR1_AWDCH_2) +#define ADC_CHANNEL_5 ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_6 ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1)) +#define ADC_CHANNEL_7 ((uint32_t)(ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_8 ((uint32_t)ADC_CR1_AWDCH_3) +#define ADC_CHANNEL_9 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_10 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1)) +#define ADC_CHANNEL_11 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_12 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2)) +#define ADC_CHANNEL_13 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_14 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1)) +#define ADC_CHANNEL_15 ((uint32_t)(ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_16 ((uint32_t)ADC_CR1_AWDCH_4) +#define ADC_CHANNEL_17 ((uint32_t)(ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_0)) +#define ADC_CHANNEL_18 ((uint32_t)(ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_1)) + +#define ADC_CHANNEL_VREFINT ((uint32_t)ADC_CHANNEL_17) +#define ADC_CHANNEL_VBAT ((uint32_t)ADC_CHANNEL_18) +/** + * @} + */ + +/** @defgroup ADC_sampling_times ADC Sampling Times + * @{ + */ +#define ADC_SAMPLETIME_3CYCLES 0x00000000U +#define ADC_SAMPLETIME_15CYCLES ((uint32_t)ADC_SMPR1_SMP10_0) +#define ADC_SAMPLETIME_28CYCLES ((uint32_t)ADC_SMPR1_SMP10_1) +#define ADC_SAMPLETIME_56CYCLES ((uint32_t)(ADC_SMPR1_SMP10_1 | ADC_SMPR1_SMP10_0)) +#define ADC_SAMPLETIME_84CYCLES ((uint32_t)ADC_SMPR1_SMP10_2) +#define ADC_SAMPLETIME_112CYCLES ((uint32_t)(ADC_SMPR1_SMP10_2 | ADC_SMPR1_SMP10_0)) +#define ADC_SAMPLETIME_144CYCLES ((uint32_t)(ADC_SMPR1_SMP10_2 | ADC_SMPR1_SMP10_1)) +#define ADC_SAMPLETIME_480CYCLES ((uint32_t)ADC_SMPR1_SMP10) +/** + * @} + */ + +/** @defgroup ADC_EOCSelection ADC EOC Selection + * @{ + */ +#define ADC_EOC_SEQ_CONV 0x00000000U +#define ADC_EOC_SINGLE_CONV 0x00000001U +#define ADC_EOC_SINGLE_SEQ_CONV 0x00000002U /*!< reserved for future use */ +/** + * @} + */ + +/** @defgroup ADC_Event_type ADC Event Type + * @{ + */ +#define ADC_AWD_EVENT ((uint32_t)ADC_FLAG_AWD) +#define ADC_OVR_EVENT ((uint32_t)ADC_FLAG_OVR) +/** + * @} + */ + +/** @defgroup ADC_analog_watchdog_selection ADC Analog Watchdog Selection + * @{ + */ +#define ADC_ANALOGWATCHDOG_SINGLE_REG ((uint32_t)(ADC_CR1_AWDSGL | ADC_CR1_AWDEN)) +#define ADC_ANALOGWATCHDOG_SINGLE_INJEC ((uint32_t)(ADC_CR1_AWDSGL | ADC_CR1_JAWDEN)) +#define ADC_ANALOGWATCHDOG_SINGLE_REGINJEC ((uint32_t)(ADC_CR1_AWDSGL | ADC_CR1_AWDEN | ADC_CR1_JAWDEN)) +#define ADC_ANALOGWATCHDOG_ALL_REG ((uint32_t)ADC_CR1_AWDEN) +#define ADC_ANALOGWATCHDOG_ALL_INJEC ((uint32_t)ADC_CR1_JAWDEN) +#define ADC_ANALOGWATCHDOG_ALL_REGINJEC ((uint32_t)(ADC_CR1_AWDEN | ADC_CR1_JAWDEN)) +#define ADC_ANALOGWATCHDOG_NONE 0x00000000U +/** + * @} + */ + +/** @defgroup ADC_interrupts_definition ADC Interrupts Definition + * @{ + */ +#define ADC_IT_EOC ((uint32_t)ADC_CR1_EOCIE) +#define ADC_IT_AWD ((uint32_t)ADC_CR1_AWDIE) +#define ADC_IT_JEOC ((uint32_t)ADC_CR1_JEOCIE) +#define ADC_IT_OVR ((uint32_t)ADC_CR1_OVRIE) +/** + * @} + */ + +/** @defgroup ADC_flags_definition ADC Flags Definition + * @{ + */ +#define ADC_FLAG_AWD ((uint32_t)ADC_SR_AWD) +#define ADC_FLAG_EOC ((uint32_t)ADC_SR_EOC) +#define ADC_FLAG_JEOC ((uint32_t)ADC_SR_JEOC) +#define ADC_FLAG_JSTRT ((uint32_t)ADC_SR_JSTRT) +#define ADC_FLAG_STRT ((uint32_t)ADC_SR_STRT) +#define ADC_FLAG_OVR ((uint32_t)ADC_SR_OVR) +/** + * @} + */ + +/** @defgroup ADC_channels_type ADC Channels Type + * @{ + */ +#define ADC_ALL_CHANNELS 0x00000001U +#define ADC_REGULAR_CHANNELS 0x00000002U /*!< reserved for future use */ +#define ADC_INJECTED_CHANNELS 0x00000003U /*!< reserved for future use */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup ADC_Exported_Macros ADC Exported Macros + * @{ + */ + +/** @brief Reset ADC handle state + * @param __HANDLE__ ADC handle + * @retval None + */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +#define __HAL_ADC_RESET_HANDLE_STATE(__HANDLE__) \ + do{ \ + (__HANDLE__)->State = HAL_ADC_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ADC_RESET_HANDLE_STATE(__HANDLE__) \ + ((__HANDLE__)->State = HAL_ADC_STATE_RESET) +#endif + +/** + * @brief Enable the ADC peripheral. + * @param __HANDLE__ ADC handle + * @retval None + */ +#define __HAL_ADC_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR2 |= ADC_CR2_ADON) + +/** + * @brief Disable the ADC peripheral. + * @param __HANDLE__ ADC handle + * @retval None + */ +#define __HAL_ADC_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR2 &= ~ADC_CR2_ADON) + +/** + * @brief Enable the ADC end of conversion interrupt. + * @param __HANDLE__ specifies the ADC Handle. + * @param __INTERRUPT__ ADC Interrupt. + * @retval None + */ +#define __HAL_ADC_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR1) |= (__INTERRUPT__)) + +/** + * @brief Disable the ADC end of conversion interrupt. + * @param __HANDLE__ specifies the ADC Handle. + * @param __INTERRUPT__ ADC interrupt. + * @retval None + */ +#define __HAL_ADC_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR1) &= ~(__INTERRUPT__)) + +/** @brief Check if the specified ADC interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the ADC Handle. + * @param __INTERRUPT__ specifies the ADC interrupt source to check. + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_ADC_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR1 & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clear the ADC's pending flags. + * @param __HANDLE__ specifies the ADC Handle. + * @param __FLAG__ ADC flag. + * @retval None + */ +#define __HAL_ADC_CLEAR_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR) = ~(__FLAG__)) + +/** + * @brief Get the selected ADC's flag status. + * @param __HANDLE__ specifies the ADC Handle. + * @param __FLAG__ ADC flag. + * @retval None + */ +#define __HAL_ADC_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) + +/** + * @} + */ + +/* Include ADC HAL Extension module */ +#include "stm32f4xx_hal_adc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup ADC_Exported_Functions + * @{ + */ + +/** @addtogroup ADC_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ***********************************/ +HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc); +void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc); +void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc); + +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +/* Callbacks Register/UnRegister functions ***********************************/ +HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup ADC_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ******************************************************/ +HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout); + +HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef *hadc, uint32_t EventType, uint32_t Timeout); + +HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc); + +void HAL_ADC_IRQHandler(ADC_HandleTypeDef *hadc); + +HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc); + +uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc); + +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc); +void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc); +void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc); +void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc); +/** + * @} + */ + +/** @addtogroup ADC_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions *************************************************/ +HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, ADC_ChannelConfTypeDef *sConfig); +HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef *hadc, ADC_AnalogWDGConfTypeDef *AnalogWDGConfig); +/** + * @} + */ + +/** @addtogroup ADC_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions ***************************************************/ +uint32_t HAL_ADC_GetState(ADC_HandleTypeDef *hadc); +uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup ADC_Private_Constants ADC Private Constants + * @{ + */ +/* Delay for ADC stabilization time. */ +/* Maximum delay is 1us (refer to device datasheet, parameter tSTAB). */ +/* Unit: us */ +#define ADC_STAB_DELAY_US 3U +/* Delay for temperature sensor stabilization time. */ +/* Maximum delay is 10us (refer to device datasheet, parameter tSTART). */ +/* Unit: us */ +#define ADC_TEMPSENSOR_DELAY_US 10U +/** + * @} + */ + +/* Private macro ------------------------------------------------------------*/ + +/** @defgroup ADC_Private_Macros ADC Private Macros + * @{ + */ +/* Macro reserved for internal HAL driver usage, not intended to be used in + code of final user */ + +/** + * @brief Verification of ADC state: enabled or disabled + * @param __HANDLE__ ADC handle + * @retval SET (ADC enabled) or RESET (ADC disabled) + */ +#define ADC_IS_ENABLE(__HANDLE__) \ + ((( ((__HANDLE__)->Instance->SR & ADC_SR_ADONS) == ADC_SR_ADONS ) \ + ) ? SET : RESET) + +/** + * @brief Test if conversion trigger of regular group is software start + * or external trigger. + * @param __HANDLE__ ADC handle + * @retval SET (software start) or RESET (external trigger) + */ +#define ADC_IS_SOFTWARE_START_REGULAR(__HANDLE__) \ + (((__HANDLE__)->Instance->CR2 & ADC_CR2_EXTEN) == RESET) + +/** + * @brief Test if conversion trigger of injected group is software start + * or external trigger. + * @param __HANDLE__ ADC handle + * @retval SET (software start) or RESET (external trigger) + */ +#define ADC_IS_SOFTWARE_START_INJECTED(__HANDLE__) \ + (((__HANDLE__)->Instance->CR2 & ADC_CR2_JEXTEN) == RESET) + +/** + * @brief Simultaneously clears and sets specific bits of the handle State + * @note: ADC_STATE_CLR_SET() macro is merely aliased to generic macro MODIFY_REG(), + * the first parameter is the ADC handle State, the second parameter is the + * bit field to clear, the third and last parameter is the bit field to set. + * @retval None + */ +#define ADC_STATE_CLR_SET MODIFY_REG + +/** + * @brief Clear ADC error code (set it to error code: "no error") + * @param __HANDLE__ ADC handle + * @retval None + */ +#define ADC_CLEAR_ERRORCODE(__HANDLE__) \ + ((__HANDLE__)->ErrorCode = HAL_ADC_ERROR_NONE) + + +#define IS_ADC_CLOCKPRESCALER(ADC_CLOCK) (((ADC_CLOCK) == ADC_CLOCK_SYNC_PCLK_DIV2) || \ + ((ADC_CLOCK) == ADC_CLOCK_SYNC_PCLK_DIV4) || \ + ((ADC_CLOCK) == ADC_CLOCK_SYNC_PCLK_DIV6) || \ + ((ADC_CLOCK) == ADC_CLOCK_SYNC_PCLK_DIV8)) +#define IS_ADC_SAMPLING_DELAY(DELAY) (((DELAY) == ADC_TWOSAMPLINGDELAY_5CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_6CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_7CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_8CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_9CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_10CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_11CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_12CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_13CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_14CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_15CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_16CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_17CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_18CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_19CYCLES) || \ + ((DELAY) == ADC_TWOSAMPLINGDELAY_20CYCLES)) +#define IS_ADC_RESOLUTION(RESOLUTION) (((RESOLUTION) == ADC_RESOLUTION_12B) || \ + ((RESOLUTION) == ADC_RESOLUTION_10B) || \ + ((RESOLUTION) == ADC_RESOLUTION_8B) || \ + ((RESOLUTION) == ADC_RESOLUTION_6B)) +#define IS_ADC_EXT_TRIG_EDGE(EDGE) (((EDGE) == ADC_EXTERNALTRIGCONVEDGE_NONE) || \ + ((EDGE) == ADC_EXTERNALTRIGCONVEDGE_RISING) || \ + ((EDGE) == ADC_EXTERNALTRIGCONVEDGE_FALLING) || \ + ((EDGE) == ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING)) +#define IS_ADC_EXT_TRIG(REGTRIG) (((REGTRIG) == ADC_EXTERNALTRIGCONV_T1_CC1) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T1_CC2) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T1_CC3) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T2_CC2) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T2_CC3) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T2_CC4) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T2_TRGO) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T3_CC1) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T3_TRGO) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T4_CC4) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T5_CC1) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T5_CC2) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T5_CC3) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T8_CC1) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_T8_TRGO) || \ + ((REGTRIG) == ADC_EXTERNALTRIGCONV_Ext_IT11)|| \ + ((REGTRIG) == ADC_SOFTWARE_START)) +#define IS_ADC_DATA_ALIGN(ALIGN) (((ALIGN) == ADC_DATAALIGN_RIGHT) || \ + ((ALIGN) == ADC_DATAALIGN_LEFT)) +#define IS_ADC_SAMPLE_TIME(TIME) (((TIME) == ADC_SAMPLETIME_3CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_15CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_28CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_56CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_84CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_112CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_144CYCLES) || \ + ((TIME) == ADC_SAMPLETIME_480CYCLES)) +#define IS_ADC_EOCSelection(EOCSelection) (((EOCSelection) == ADC_EOC_SINGLE_CONV) || \ + ((EOCSelection) == ADC_EOC_SEQ_CONV) || \ + ((EOCSelection) == ADC_EOC_SINGLE_SEQ_CONV)) +#define IS_ADC_EVENT_TYPE(EVENT) (((EVENT) == ADC_AWD_EVENT) || \ + ((EVENT) == ADC_OVR_EVENT)) +#define IS_ADC_ANALOG_WATCHDOG(WATCHDOG) (((WATCHDOG) == ADC_ANALOGWATCHDOG_SINGLE_REG) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_SINGLE_INJEC) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_SINGLE_REGINJEC) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_ALL_REG) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_ALL_INJEC) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_ALL_REGINJEC) || \ + ((WATCHDOG) == ADC_ANALOGWATCHDOG_NONE)) +#define IS_ADC_CHANNELS_TYPE(CHANNEL_TYPE) (((CHANNEL_TYPE) == ADC_ALL_CHANNELS) || \ + ((CHANNEL_TYPE) == ADC_REGULAR_CHANNELS) || \ + ((CHANNEL_TYPE) == ADC_INJECTED_CHANNELS)) +#define IS_ADC_THRESHOLD(THRESHOLD) ((THRESHOLD) <= 0xFFFU) + +#define IS_ADC_REGULAR_LENGTH(LENGTH) (((LENGTH) >= 1U) && ((LENGTH) <= 16U)) +#define IS_ADC_REGULAR_RANK(RANK) (((RANK) >= 1U) && ((RANK) <= (16U))) +#define IS_ADC_REGULAR_DISC_NUMBER(NUMBER) (((NUMBER) >= 1U) && ((NUMBER) <= 8U)) +#define IS_ADC_RANGE(RESOLUTION, ADC_VALUE) \ + ((((RESOLUTION) == ADC_RESOLUTION_12B) && ((ADC_VALUE) <= 0x0FFFU)) || \ + (((RESOLUTION) == ADC_RESOLUTION_10B) && ((ADC_VALUE) <= 0x03FFU)) || \ + (((RESOLUTION) == ADC_RESOLUTION_8B) && ((ADC_VALUE) <= 0x00FFU)) || \ + (((RESOLUTION) == ADC_RESOLUTION_6B) && ((ADC_VALUE) <= 0x003FU))) + +/** + * @brief Set ADC Regular channel sequence length. + * @param _NbrOfConversion_ Regular channel sequence length. + * @retval None + */ +#define ADC_SQR1(_NbrOfConversion_) (((_NbrOfConversion_) - (uint8_t)1U) << 20U) + +/** + * @brief Set the ADC's sample time for channel numbers between 10 and 18. + * @param _SAMPLETIME_ Sample time parameter. + * @param _CHANNELNB_ Channel number. + * @retval None + */ +#define ADC_SMPR1(_SAMPLETIME_, _CHANNELNB_) ((_SAMPLETIME_) << (3U * (((uint32_t)((uint16_t)(_CHANNELNB_))) - 10U))) + +/** + * @brief Set the ADC's sample time for channel numbers between 0 and 9. + * @param _SAMPLETIME_ Sample time parameter. + * @param _CHANNELNB_ Channel number. + * @retval None + */ +#define ADC_SMPR2(_SAMPLETIME_, _CHANNELNB_) ((_SAMPLETIME_) << (3U * ((uint32_t)((uint16_t)(_CHANNELNB_))))) + +/** + * @brief Set the selected regular channel rank for rank between 1 and 6. + * @param _CHANNELNB_ Channel number. + * @param _RANKNB_ Rank number. + * @retval None + */ +#define ADC_SQR3_RK(_CHANNELNB_, _RANKNB_) (((uint32_t)((uint16_t)(_CHANNELNB_))) << (5U * ((_RANKNB_) - 1U))) + +/** + * @brief Set the selected regular channel rank for rank between 7 and 12. + * @param _CHANNELNB_ Channel number. + * @param _RANKNB_ Rank number. + * @retval None + */ +#define ADC_SQR2_RK(_CHANNELNB_, _RANKNB_) (((uint32_t)((uint16_t)(_CHANNELNB_))) << (5U * ((_RANKNB_) - 7U))) + +/** + * @brief Set the selected regular channel rank for rank between 13 and 16. + * @param _CHANNELNB_ Channel number. + * @param _RANKNB_ Rank number. + * @retval None + */ +#define ADC_SQR1_RK(_CHANNELNB_, _RANKNB_) (((uint32_t)((uint16_t)(_CHANNELNB_))) << (5U * ((_RANKNB_) - 13U))) + +/** + * @brief Enable ADC continuous conversion mode. + * @param _CONTINUOUS_MODE_ Continuous mode. + * @retval None + */ +#define ADC_CR2_CONTINUOUS(_CONTINUOUS_MODE_) ((_CONTINUOUS_MODE_) << 1U) + +/** + * @brief Configures the number of discontinuous conversions for the regular group channels. + * @param _NBR_DISCONTINUOUSCONV_ Number of discontinuous conversions. + * @retval None + */ +#define ADC_CR1_DISCONTINUOUS(_NBR_DISCONTINUOUSCONV_) (((_NBR_DISCONTINUOUSCONV_) - 1U) << ADC_CR1_DISCNUM_Pos) + +/** + * @brief Enable ADC scan mode. + * @param _SCANCONV_MODE_ Scan conversion mode. + * @retval None + */ +#define ADC_CR1_SCANCONV(_SCANCONV_MODE_) ((_SCANCONV_MODE_) << 8U) + +/** + * @brief Enable the ADC end of conversion selection. + * @param _EOCSelection_MODE_ End of conversion selection mode. + * @retval None + */ +#define ADC_CR2_EOCSelection(_EOCSelection_MODE_) ((_EOCSelection_MODE_) << 10U) + +/** + * @brief Enable the ADC DMA continuous request. + * @param _DMAContReq_MODE_ DMA continuous request mode. + * @retval None + */ +#define ADC_CR2_DMAContReq(_DMAContReq_MODE_) ((_DMAContReq_MODE_) << 9U) + +/** + * @brief Return resolution bits in CR1 register. + * @param __HANDLE__ ADC handle + * @retval None + */ +#define ADC_GET_RESOLUTION(__HANDLE__) (((__HANDLE__)->Instance->CR1) & ADC_CR1_RES) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup ADC_Private_Functions ADC Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_ADC_H */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h new file mode 100644 index 0000000..8ce8484 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_adc_ex.h @@ -0,0 +1,407 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_adc_ex.h + * @author MCD Application Team + * @brief Header file of ADC HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_ADC_EX_H +#define __STM32F4xx_ADC_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup ADCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup ADCEx_Exported_Types ADC Exported Types + * @{ + */ + +/** + * @brief ADC Configuration injected Channel structure definition + * @note Parameters of this structure are shared within 2 scopes: + * - Scope channel: InjectedChannel, InjectedRank, InjectedSamplingTime, InjectedOffset + * - Scope injected group (affects all channels of injected group): InjectedNbrOfConversion, InjectedDiscontinuousConvMode, + * AutoInjectedConv, ExternalTrigInjecConvEdge, ExternalTrigInjecConv. + * @note The setting of these parameters with function HAL_ADCEx_InjectedConfigChannel() is conditioned to ADC state. + * ADC state can be either: + * - For all parameters: ADC disabled + * - For all except parameters 'InjectedDiscontinuousConvMode' and 'AutoInjectedConv': ADC enabled without conversion on going on injected group. + * - For parameters 'ExternalTrigInjecConv' and 'ExternalTrigInjecConvEdge': ADC enabled, even with conversion on going on injected group. + */ +typedef struct +{ + uint32_t InjectedChannel; /*!< Selection of ADC channel to configure + This parameter can be a value of @ref ADC_channels + Note: Depending on devices, some channels may not be available on package pins. Refer to device datasheet for channels availability. */ + uint32_t InjectedRank; /*!< Rank in the injected group sequencer + This parameter must be a value of @ref ADCEx_injected_rank + Note: In case of need to disable a channel or change order of conversion sequencer, rank containing a previous channel setting can be overwritten by the new channel setting (or parameter number of conversions can be adjusted) */ + uint32_t InjectedSamplingTime; /*!< Sampling time value to be set for the selected channel. + Unit: ADC clock cycles + Conversion time is the addition of sampling time and processing time (12 ADC clock cycles at ADC resolution 12 bits, 11 cycles at 10 bits, 9 cycles at 8 bits, 7 cycles at 6 bits). + This parameter can be a value of @ref ADC_sampling_times + Caution: This parameter updates the parameter property of the channel, that can be used into regular and/or injected groups. + If this same channel has been previously configured in the other group (regular/injected), it will be updated to last setting. + Note: In case of usage of internal measurement channels (VrefInt/Vbat/TempSensor), + sampling time constraints must be respected (sampling time can be adjusted in function of ADC clock frequency and sampling time setting) + Refer to device datasheet for timings values, parameters TS_vrefint, TS_temp (values rough order: 4us min). */ + uint32_t InjectedOffset; /*!< Defines the offset to be subtracted from the raw converted data (for channels set on injected group only). + Offset value must be a positive number. + Depending of ADC resolution selected (12, 10, 8 or 6 bits), + this parameter must be a number between Min_Data = 0x000 and Max_Data = 0xFFF, 0x3FF, 0xFF or 0x3F respectively. */ + uint32_t InjectedNbrOfConversion; /*!< Specifies the number of ranks that will be converted within the injected group sequencer. + To use the injected group sequencer and convert several ranks, parameter 'ScanConvMode' must be enabled. + This parameter must be a number between Min_Data = 1 and Max_Data = 4. + Caution: this setting impacts the entire injected group. Therefore, call of HAL_ADCEx_InjectedConfigChannel() to + configure a channel on injected group can impact the configuration of other channels previously set. */ + FunctionalState InjectedDiscontinuousConvMode; /*!< Specifies whether the conversions sequence of injected group is performed in Complete-sequence/Discontinuous-sequence (main sequence subdivided in successive parts). + Discontinuous mode is used only if sequencer is enabled (parameter 'ScanConvMode'). If sequencer is disabled, this parameter is discarded. + Discontinuous mode can be enabled only if continuous mode is disabled. If continuous mode is enabled, this parameter setting is discarded. + This parameter can be set to ENABLE or DISABLE. + Note: For injected group, number of discontinuous ranks increment is fixed to one-by-one. + Caution: this setting impacts the entire injected group. Therefore, call of HAL_ADCEx_InjectedConfigChannel() to + configure a channel on injected group can impact the configuration of other channels previously set. */ + FunctionalState AutoInjectedConv; /*!< Enables or disables the selected ADC automatic injected group conversion after regular one + This parameter can be set to ENABLE or DISABLE. + Note: To use Automatic injected conversion, discontinuous mode must be disabled ('DiscontinuousConvMode' and 'InjectedDiscontinuousConvMode' set to DISABLE) + Note: To use Automatic injected conversion, injected group external triggers must be disabled ('ExternalTrigInjecConv' set to ADC_SOFTWARE_START) + Note: In case of DMA used with regular group: if DMA configured in normal mode (single shot) JAUTO will be stopped upon DMA transfer complete. + To maintain JAUTO always enabled, DMA must be configured in circular mode. + Caution: this setting impacts the entire injected group. Therefore, call of HAL_ADCEx_InjectedConfigChannel() to + configure a channel on injected group can impact the configuration of other channels previously set. */ + uint32_t ExternalTrigInjecConv; /*!< Selects the external event used to trigger the conversion start of injected group. + If set to ADC_INJECTED_SOFTWARE_START, external triggers are disabled. + If set to external trigger source, triggering is on event rising edge. + This parameter can be a value of @ref ADCEx_External_trigger_Source_Injected + Note: This parameter must be modified when ADC is disabled (before ADC start conversion or after ADC stop conversion). + If ADC is enabled, this parameter setting is bypassed without error reporting (as it can be the expected behaviour in case of another parameter update on the fly) + Caution: this setting impacts the entire injected group. Therefore, call of HAL_ADCEx_InjectedConfigChannel() to + configure a channel on injected group can impact the configuration of other channels previously set. */ + uint32_t ExternalTrigInjecConvEdge; /*!< Selects the external trigger edge of injected group. + This parameter can be a value of @ref ADCEx_External_trigger_edge_Injected. + If trigger is set to ADC_INJECTED_SOFTWARE_START, this parameter is discarded. + Caution: this setting impacts the entire injected group. Therefore, call of HAL_ADCEx_InjectedConfigChannel() to + configure a channel on injected group can impact the configuration of other channels previously set. */ +} ADC_InjectionConfTypeDef; + +/** + * @brief ADC Configuration multi-mode structure definition + */ +typedef struct +{ + uint32_t Mode; /*!< Configures the ADC to operate in independent or multi mode. + This parameter can be a value of @ref ADCEx_Common_mode */ + uint32_t DMAAccessMode; /*!< Configures the Direct memory access mode for multi ADC mode. + This parameter can be a value of @ref ADCEx_Direct_memory_access_mode_for_multi_mode */ + uint32_t TwoSamplingDelay; /*!< Configures the Delay between 2 sampling phases. + This parameter can be a value of @ref ADC_delay_between_2_sampling_phases */ +} ADC_MultiModeTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ADCEx_Exported_Constants ADC Exported Constants + * @{ + */ + +/** @defgroup ADCEx_Common_mode ADC Common Mode + * @{ + */ +#define ADC_MODE_INDEPENDENT 0x00000000U +#define ADC_DUALMODE_REGSIMULT_INJECSIMULT ((uint32_t)ADC_CCR_MULTI_0) +#define ADC_DUALMODE_REGSIMULT_ALTERTRIG ((uint32_t)ADC_CCR_MULTI_1) +#define ADC_DUALMODE_INJECSIMULT ((uint32_t)(ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0)) +#define ADC_DUALMODE_REGSIMULT ((uint32_t)(ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1)) +#define ADC_DUALMODE_INTERL ((uint32_t)(ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 | ADC_CCR_MULTI_0)) +#define ADC_DUALMODE_ALTERTRIG ((uint32_t)(ADC_CCR_MULTI_3 | ADC_CCR_MULTI_0)) +#define ADC_TRIPLEMODE_REGSIMULT_INJECSIMULT ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_0)) +#define ADC_TRIPLEMODE_REGSIMULT_AlterTrig ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_1)) +#define ADC_TRIPLEMODE_INJECSIMULT ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0)) +#define ADC_TRIPLEMODE_REGSIMULT ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1)) +#define ADC_TRIPLEMODE_INTERL ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 | ADC_CCR_MULTI_0)) +#define ADC_TRIPLEMODE_ALTERTRIG ((uint32_t)(ADC_CCR_MULTI_4 | ADC_CCR_MULTI_3 | ADC_CCR_MULTI_0)) +/** + * @} + */ + +/** @defgroup ADCEx_Direct_memory_access_mode_for_multi_mode ADC Direct Memory Access Mode For Multi Mode + * @{ + */ +#define ADC_DMAACCESSMODE_DISABLED 0x00000000U /*!< DMA mode disabled */ +#define ADC_DMAACCESSMODE_1 ((uint32_t)ADC_CCR_DMA_0) /*!< DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)*/ +#define ADC_DMAACCESSMODE_2 ((uint32_t)ADC_CCR_DMA_1) /*!< DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)*/ +#define ADC_DMAACCESSMODE_3 ((uint32_t)ADC_CCR_DMA) /*!< DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2) */ +/** + * @} + */ + +/** @defgroup ADCEx_External_trigger_edge_Injected ADC External Trigger Edge Injected + * @{ + */ +#define ADC_EXTERNALTRIGINJECCONVEDGE_NONE 0x00000000U +#define ADC_EXTERNALTRIGINJECCONVEDGE_RISING ((uint32_t)ADC_CR2_JEXTEN_0) +#define ADC_EXTERNALTRIGINJECCONVEDGE_FALLING ((uint32_t)ADC_CR2_JEXTEN_1) +#define ADC_EXTERNALTRIGINJECCONVEDGE_RISINGFALLING ((uint32_t)ADC_CR2_JEXTEN) +/** + * @} + */ + +/** @defgroup ADCEx_External_trigger_Source_Injected ADC External Trigger Source Injected + * @{ + */ +#define ADC_EXTERNALTRIGINJECCONV_T1_CC4 0x00000000U +#define ADC_EXTERNALTRIGINJECCONV_T1_TRGO ((uint32_t)ADC_CR2_JEXTSEL_0) +#define ADC_EXTERNALTRIGINJECCONV_T2_CC1 ((uint32_t)ADC_CR2_JEXTSEL_1) +#define ADC_EXTERNALTRIGINJECCONV_T2_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T3_CC2 ((uint32_t)ADC_CR2_JEXTSEL_2) +#define ADC_EXTERNALTRIGINJECCONV_T3_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T4_CC1 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1)) +#define ADC_EXTERNALTRIGINJECCONV_T4_CC2 ((uint32_t)(ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T4_CC3 ((uint32_t)ADC_CR2_JEXTSEL_3) +#define ADC_EXTERNALTRIGINJECCONV_T4_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T5_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1)) +#define ADC_EXTERNALTRIGINJECCONV_T5_TRGO ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T8_CC2 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2)) +#define ADC_EXTERNALTRIGINJECCONV_T8_CC3 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0)) +#define ADC_EXTERNALTRIGINJECCONV_T8_CC4 ((uint32_t)(ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1)) +#define ADC_EXTERNALTRIGINJECCONV_EXT_IT15 ((uint32_t)ADC_CR2_JEXTSEL) +#define ADC_INJECTED_SOFTWARE_START ((uint32_t)ADC_CR2_JEXTSEL + 1U) +/** + * @} + */ + +/** @defgroup ADCEx_injected_rank ADC Injected Rank + * @{ + */ +#define ADC_INJECTED_RANK_1 0x00000001U +#define ADC_INJECTED_RANK_2 0x00000002U +#define ADC_INJECTED_RANK_3 0x00000003U +#define ADC_INJECTED_RANK_4 0x00000004U +/** + * @} + */ + +/** @defgroup ADCEx_channels ADC Specific Channels + * @{ + */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || \ + defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || \ + defined(STM32F410Rx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || \ + defined(STM32F412Cx) +#define ADC_CHANNEL_TEMPSENSOR ((uint32_t)ADC_CHANNEL_16) +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE || STM32F410xx || STM32F412Zx || + STM32F412Vx || STM32F412Rx || STM32F412Cx */ + +#if defined(STM32F411xE) || defined(STM32F413xx) || defined(STM32F423xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#define ADC_CHANNEL_DIFFERENCIATION_TEMPSENSOR_VBAT 0x10000000U /* Dummy bit for driver internal usage, not used in ADC channel setting registers CR1 or SQRx */ +#define ADC_CHANNEL_TEMPSENSOR ((uint32_t)ADC_CHANNEL_18 | ADC_CHANNEL_DIFFERENCIATION_TEMPSENSOR_VBAT) +#endif /* STM32F411xE || STM32F413xx || STM32F423xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup ADC_Exported_Macros ADC Exported Macros + * @{ + */ +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) +/** + * @brief Disable internal path of ADC channel Vbat + * @note Use case of this macro: + * On devices STM32F42x and STM32F43x, ADC internal channels + * Vbat and VrefInt share the same internal path, only + * one of them can be enabled.This macro is to be used when ADC + * channels Vbat and VrefInt are selected, and must be called + * before starting conversion of ADC channel VrefInt in order + * to disable ADC channel Vbat. + * @retval None + */ +#define __HAL_ADC_PATH_INTERNAL_VBAT_DISABLE() (ADC->CCR &= ~(ADC_CCR_VBATE)) +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup ADCEx_Exported_Functions + * @{ + */ + +/** @addtogroup ADCEx_Exported_Functions_Group1 + * @{ + */ + +/* I/O operation functions ******************************************************/ +HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout); +HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef *hadc); +HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef *hadc); +uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef *hadc, uint32_t InjectedRank); +HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc); +uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef *hadc); +void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc); + +/* Peripheral Control functions *************************************************/ +HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef *hadc, ADC_InjectionConfTypeDef *sConfigInjected); +HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef *hadc, ADC_MultiModeTypeDef *multimode); + +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup ADCEx_Private_Constants ADC Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ADCEx_Private_Macros ADC Private Macros + * @{ + */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || \ + defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || \ + defined(STM32F410Rx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || \ + defined(STM32F412Cx) +#define IS_ADC_CHANNEL(CHANNEL) ((CHANNEL) <= ADC_CHANNEL_18) +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE || + STM32F410xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */ + +#if defined(STM32F411xE) || defined(STM32F413xx) || defined(STM32F423xx) || defined(STM32F427xx) || \ + defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) +#define IS_ADC_CHANNEL(CHANNEL) (((CHANNEL) <= ADC_CHANNEL_18) || \ + ((CHANNEL) == ADC_CHANNEL_TEMPSENSOR)) +#endif /* STM32F411xE || STM32F413xx || STM32F423xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ + +#define IS_ADC_MODE(MODE) (((MODE) == ADC_MODE_INDEPENDENT) || \ + ((MODE) == ADC_DUALMODE_REGSIMULT_INJECSIMULT) || \ + ((MODE) == ADC_DUALMODE_REGSIMULT_ALTERTRIG) || \ + ((MODE) == ADC_DUALMODE_INJECSIMULT) || \ + ((MODE) == ADC_DUALMODE_REGSIMULT) || \ + ((MODE) == ADC_DUALMODE_INTERL) || \ + ((MODE) == ADC_DUALMODE_ALTERTRIG) || \ + ((MODE) == ADC_TRIPLEMODE_REGSIMULT_INJECSIMULT) || \ + ((MODE) == ADC_TRIPLEMODE_REGSIMULT_AlterTrig) || \ + ((MODE) == ADC_TRIPLEMODE_INJECSIMULT) || \ + ((MODE) == ADC_TRIPLEMODE_REGSIMULT) || \ + ((MODE) == ADC_TRIPLEMODE_INTERL) || \ + ((MODE) == ADC_TRIPLEMODE_ALTERTRIG)) +#define IS_ADC_DMA_ACCESS_MODE(MODE) (((MODE) == ADC_DMAACCESSMODE_DISABLED) || \ + ((MODE) == ADC_DMAACCESSMODE_1) || \ + ((MODE) == ADC_DMAACCESSMODE_2) || \ + ((MODE) == ADC_DMAACCESSMODE_3)) +#define IS_ADC_EXT_INJEC_TRIG_EDGE(EDGE) (((EDGE) == ADC_EXTERNALTRIGINJECCONVEDGE_NONE) || \ + ((EDGE) == ADC_EXTERNALTRIGINJECCONVEDGE_RISING) || \ + ((EDGE) == ADC_EXTERNALTRIGINJECCONVEDGE_FALLING) || \ + ((EDGE) == ADC_EXTERNALTRIGINJECCONVEDGE_RISINGFALLING)) +#define IS_ADC_EXT_INJEC_TRIG(INJTRIG) (((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T1_CC4) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T1_TRGO) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T2_CC1) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T2_TRGO) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T3_CC2) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T3_CC4) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T4_CC1) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T4_CC2) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T4_CC3) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T4_TRGO) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T5_CC4) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T5_TRGO) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T8_CC2) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T8_CC3) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_T8_CC4) || \ + ((INJTRIG) == ADC_EXTERNALTRIGINJECCONV_EXT_IT15)|| \ + ((INJTRIG) == ADC_INJECTED_SOFTWARE_START)) +#define IS_ADC_INJECTED_LENGTH(LENGTH) (((LENGTH) >= 1U) && ((LENGTH) <= 4U)) +#define IS_ADC_INJECTED_RANK(RANK) (((RANK) >= 1U) && ((RANK) <= 4U)) + +/** + * @brief Set the selected injected Channel rank. + * @param _CHANNELNB_ Channel number. + * @param _RANKNB_ Rank number. + * @param _JSQR_JL_ Sequence length. + * @retval None + */ +#define ADC_JSQR(_CHANNELNB_, _RANKNB_, _JSQR_JL_) (((uint32_t)((uint16_t)(_CHANNELNB_))) << (5U * (uint8_t)(((_RANKNB_) + 3U) - (_JSQR_JL_)))) + +/** + * @brief Defines if the selected ADC is within ADC common register ADC123 or ADC1 + * if available (ADC2, ADC3 availability depends on STM32 product) + * @param __HANDLE__ ADC handle + * @retval Common control register ADC123 or ADC1 + */ +#if defined(STM32F405xx) || defined(STM32F407xx) || defined(STM32F415xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F429xx) || defined(STM32F437xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#define ADC_COMMON_REGISTER(__HANDLE__) ADC123_COMMON +#else +#define ADC_COMMON_REGISTER(__HANDLE__) ADC1_COMMON +#endif /* STM32F405xx || STM32F407xx || STM32F415xx || STM32F417xx || STM32F427xx || STM32F429xx || STM32F437xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup ADCEx_Private_Functions ADC Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*__STM32F4xx_ADC_EX_H */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h new file mode 100644 index 0000000..cf4557b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_can.h @@ -0,0 +1,853 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_can.h + * @author MCD Application Team + * @brief Header file of CAN 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 STM32F4xx_HAL_CAN_H +#define STM32F4xx_HAL_CAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined (CAN1) +/** @addtogroup CAN + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CAN_Exported_Types CAN Exported Types + * @{ + */ +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_CAN_STATE_RESET = 0x00U, /*!< CAN not yet initialized or disabled */ + HAL_CAN_STATE_READY = 0x01U, /*!< CAN initialized and ready for use */ + HAL_CAN_STATE_LISTENING = 0x02U, /*!< CAN receive process is ongoing */ + HAL_CAN_STATE_SLEEP_PENDING = 0x03U, /*!< CAN sleep request is pending */ + HAL_CAN_STATE_SLEEP_ACTIVE = 0x04U, /*!< CAN sleep mode is active */ + HAL_CAN_STATE_ERROR = 0x05U /*!< CAN error state */ + +} HAL_CAN_StateTypeDef; + +/** + * @brief CAN init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the length of a time quantum. + This parameter must be a number between Min_Data = 1 and Max_Data = 1024. */ + + uint32_t Mode; /*!< Specifies the CAN operating mode. + This parameter can be a value of @ref CAN_operating_mode */ + + uint32_t SyncJumpWidth; /*!< Specifies the maximum number of time quanta the CAN hardware + is allowed to lengthen or shorten a bit to perform resynchronization. + This parameter can be a value of @ref CAN_synchronisation_jump_width */ + + uint32_t TimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1. + This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */ + + uint32_t TimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2. + This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */ + + FunctionalState TimeTriggeredMode; /*!< Enable or disable the time triggered communication mode. + This parameter can be set to ENABLE or DISABLE. */ + + FunctionalState AutoBusOff; /*!< Enable or disable the automatic bus-off management. + This parameter can be set to ENABLE or DISABLE. */ + + FunctionalState AutoWakeUp; /*!< Enable or disable the automatic wake-up mode. + This parameter can be set to ENABLE or DISABLE. */ + + FunctionalState AutoRetransmission; /*!< Enable or disable the non-automatic retransmission mode. + This parameter can be set to ENABLE or DISABLE. */ + + FunctionalState ReceiveFifoLocked; /*!< Enable or disable the Receive FIFO Locked mode. + This parameter can be set to ENABLE or DISABLE. */ + + FunctionalState TransmitFifoPriority;/*!< Enable or disable the transmit FIFO priority. + This parameter can be set to ENABLE or DISABLE. */ + +} CAN_InitTypeDef; + +/** + * @brief CAN filter configuration structure definition + */ +typedef struct +{ + uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterMaskIdLow; /*!< Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0xFFFF. */ + + uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint32_t FilterBank; /*!< Specifies the filter bank which will be initialized. + For single CAN instance(14 dedicated filter banks), + this parameter must be a number between Min_Data = 0 and Max_Data = 13. + For dual CAN instances(28 filter banks shared), + this parameter must be a number between Min_Data = 0 and Max_Data = 27. */ + + uint32_t FilterMode; /*!< Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint32_t FilterScale; /*!< Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + uint32_t FilterActivation; /*!< Enable or disable the filter. + This parameter can be a value of @ref CAN_filter_activation */ + + uint32_t SlaveStartFilterBank; /*!< Select the start filter bank for the slave CAN instance. + For single CAN instances, this parameter is meaningless. + For dual CAN instances, all filter banks with lower index are assigned to master + CAN instance, whereas all filter banks with greater index are assigned to slave + CAN instance. + This parameter must be a number between Min_Data = 0 and Max_Data = 27. */ + +} CAN_FilterTypeDef; + +/** + * @brief CAN Tx message header structure definition + */ +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted. + This parameter can be a value of @ref CAN_identifier_type */ + + uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted. + This parameter can be a value of @ref CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted. + This parameter must be a number between Min_Data = 0 and Max_Data = 8. */ + + FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start + of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7]. + @note: Time Triggered Communication Mode must be enabled. + @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent. + This parameter can be set to ENABLE or DISABLE. */ + +} CAN_TxHeaderTypeDef; + +/** + * @brief CAN Rx message header structure definition + */ +typedef struct +{ + uint32_t StdId; /*!< Specifies the standard identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */ + + uint32_t ExtId; /*!< Specifies the extended identifier. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */ + + uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted. + This parameter can be a value of @ref CAN_identifier_type */ + + uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted. + This parameter can be a value of @ref CAN_remote_transmission_request */ + + uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted. + This parameter must be a number between Min_Data = 0 and Max_Data = 8. */ + + uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception. + @note: Time Triggered Communication Mode must be enabled. + This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */ + + uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element. + This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */ + +} CAN_RxHeaderTypeDef; + +/** + * @brief CAN handle Structure definition + */ +typedef struct __CAN_HandleTypeDef +{ + CAN_TypeDef *Instance; /*!< Register base address */ + + CAN_InitTypeDef Init; /*!< CAN required parameters */ + + __IO HAL_CAN_StateTypeDef State; /*!< CAN communication state */ + + __IO uint32_t ErrorCode; /*!< CAN Error code. + This parameter can be a value of @ref CAN_Error_Code */ + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + void (* TxMailbox0CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 0 complete callback */ + void (* TxMailbox1CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 1 complete callback */ + void (* TxMailbox2CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 2 complete callback */ + void (* TxMailbox0AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 0 abort callback */ + void (* TxMailbox1AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 1 abort callback */ + void (* TxMailbox2AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 2 abort callback */ + void (* RxFifo0MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 msg pending callback */ + void (* RxFifo0FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 full callback */ + void (* RxFifo1MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 msg pending callback */ + void (* RxFifo1FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 full callback */ + void (* SleepCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Sleep callback */ + void (* WakeUpFromRxMsgCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Wake Up from Rx msg callback */ + void (* ErrorCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Error callback */ + + void (* MspInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp Init callback */ + void (* MspDeInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp DeInit callback */ + +#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ +} CAN_HandleTypeDef; + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 +/** + * @brief HAL CAN common Callback ID enumeration definition + */ +typedef enum +{ + HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID = 0x00U, /*!< CAN Tx Mailbox 0 complete callback ID */ + HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID = 0x01U, /*!< CAN Tx Mailbox 1 complete callback ID */ + HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID = 0x02U, /*!< CAN Tx Mailbox 2 complete callback ID */ + HAL_CAN_TX_MAILBOX0_ABORT_CB_ID = 0x03U, /*!< CAN Tx Mailbox 0 abort callback ID */ + HAL_CAN_TX_MAILBOX1_ABORT_CB_ID = 0x04U, /*!< CAN Tx Mailbox 1 abort callback ID */ + HAL_CAN_TX_MAILBOX2_ABORT_CB_ID = 0x05U, /*!< CAN Tx Mailbox 2 abort callback ID */ + HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID = 0x06U, /*!< CAN Rx FIFO 0 message pending callback ID */ + HAL_CAN_RX_FIFO0_FULL_CB_ID = 0x07U, /*!< CAN Rx FIFO 0 full callback ID */ + HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID = 0x08U, /*!< CAN Rx FIFO 1 message pending callback ID */ + HAL_CAN_RX_FIFO1_FULL_CB_ID = 0x09U, /*!< CAN Rx FIFO 1 full callback ID */ + HAL_CAN_SLEEP_CB_ID = 0x0AU, /*!< CAN Sleep callback ID */ + HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID = 0x0BU, /*!< CAN Wake Up from Rx msg callback ID */ + HAL_CAN_ERROR_CB_ID = 0x0CU, /*!< CAN Error callback ID */ + + HAL_CAN_MSPINIT_CB_ID = 0x0DU, /*!< CAN MspInit callback ID */ + HAL_CAN_MSPDEINIT_CB_ID = 0x0EU, /*!< CAN MspDeInit callback ID */ + +} HAL_CAN_CallbackIDTypeDef; + +/** + * @brief HAL CAN Callback pointer definition + */ +typedef void (*pCAN_CallbackTypeDef)(CAN_HandleTypeDef *hcan); /*!< pointer to a CAN callback function */ + +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup CAN_Exported_Constants CAN Exported Constants + * @{ + */ + +/** @defgroup CAN_Error_Code CAN Error Code + * @{ + */ +#define HAL_CAN_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_CAN_ERROR_EWG (0x00000001U) /*!< Protocol Error Warning */ +#define HAL_CAN_ERROR_EPV (0x00000002U) /*!< Error Passive */ +#define HAL_CAN_ERROR_BOF (0x00000004U) /*!< Bus-off error */ +#define HAL_CAN_ERROR_STF (0x00000008U) /*!< Stuff error */ +#define HAL_CAN_ERROR_FOR (0x00000010U) /*!< Form error */ +#define HAL_CAN_ERROR_ACK (0x00000020U) /*!< Acknowledgment error */ +#define HAL_CAN_ERROR_BR (0x00000040U) /*!< Bit recessive error */ +#define HAL_CAN_ERROR_BD (0x00000080U) /*!< Bit dominant error */ +#define HAL_CAN_ERROR_CRC (0x00000100U) /*!< CRC error */ +#define HAL_CAN_ERROR_RX_FOV0 (0x00000200U) /*!< Rx FIFO0 overrun error */ +#define HAL_CAN_ERROR_RX_FOV1 (0x00000400U) /*!< Rx FIFO1 overrun error */ +#define HAL_CAN_ERROR_TX_ALST0 (0x00000800U) /*!< TxMailbox 0 transmit failure due to arbitration lost */ +#define HAL_CAN_ERROR_TX_TERR0 (0x00001000U) /*!< TxMailbox 0 transmit failure due to transmit error */ +#define HAL_CAN_ERROR_TX_ALST1 (0x00002000U) /*!< TxMailbox 1 transmit failure due to arbitration lost */ +#define HAL_CAN_ERROR_TX_TERR1 (0x00004000U) /*!< TxMailbox 1 transmit failure due to transmit error */ +#define HAL_CAN_ERROR_TX_ALST2 (0x00008000U) /*!< TxMailbox 2 transmit failure due to arbitration lost */ +#define HAL_CAN_ERROR_TX_TERR2 (0x00010000U) /*!< TxMailbox 2 transmit failure due to transmit error */ +#define HAL_CAN_ERROR_TIMEOUT (0x00020000U) /*!< Timeout error */ +#define HAL_CAN_ERROR_NOT_INITIALIZED (0x00040000U) /*!< Peripheral not initialized */ +#define HAL_CAN_ERROR_NOT_READY (0x00080000U) /*!< Peripheral not ready */ +#define HAL_CAN_ERROR_NOT_STARTED (0x00100000U) /*!< Peripheral not started */ +#define HAL_CAN_ERROR_PARAM (0x00200000U) /*!< Parameter error */ + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 +#define HAL_CAN_ERROR_INVALID_CALLBACK (0x00400000U) /*!< Invalid Callback error */ +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ +#define HAL_CAN_ERROR_INTERNAL (0x00800000U) /*!< Internal error */ + +/** + * @} + */ + +/** @defgroup CAN_InitStatus CAN InitStatus + * @{ + */ +#define CAN_INITSTATUS_FAILED (0x00000000U) /*!< CAN initialization failed */ +#define CAN_INITSTATUS_SUCCESS (0x00000001U) /*!< CAN initialization OK */ +/** + * @} + */ + +/** @defgroup CAN_operating_mode CAN Operating Mode + * @{ + */ +#define CAN_MODE_NORMAL (0x00000000U) /*!< Normal mode */ +#define CAN_MODE_LOOPBACK ((uint32_t)CAN_BTR_LBKM) /*!< Loopback mode */ +#define CAN_MODE_SILENT ((uint32_t)CAN_BTR_SILM) /*!< Silent mode */ +#define CAN_MODE_SILENT_LOOPBACK ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM)) /*!< Loopback combined with + silent mode */ +/** + * @} + */ + + +/** @defgroup CAN_synchronisation_jump_width CAN Synchronization Jump Width + * @{ + */ +#define CAN_SJW_1TQ (0x00000000U) /*!< 1 time quantum */ +#define CAN_SJW_2TQ ((uint32_t)CAN_BTR_SJW_0) /*!< 2 time quantum */ +#define CAN_SJW_3TQ ((uint32_t)CAN_BTR_SJW_1) /*!< 3 time quantum */ +#define CAN_SJW_4TQ ((uint32_t)CAN_BTR_SJW) /*!< 4 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_1 CAN Time Quantum in Bit Segment 1 + * @{ + */ +#define CAN_BS1_1TQ (0x00000000U) /*!< 1 time quantum */ +#define CAN_BS1_2TQ ((uint32_t)CAN_BTR_TS1_0) /*!< 2 time quantum */ +#define CAN_BS1_3TQ ((uint32_t)CAN_BTR_TS1_1) /*!< 3 time quantum */ +#define CAN_BS1_4TQ ((uint32_t)(CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 4 time quantum */ +#define CAN_BS1_5TQ ((uint32_t)CAN_BTR_TS1_2) /*!< 5 time quantum */ +#define CAN_BS1_6TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 6 time quantum */ +#define CAN_BS1_7TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 7 time quantum */ +#define CAN_BS1_8TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 8 time quantum */ +#define CAN_BS1_9TQ ((uint32_t)CAN_BTR_TS1_3) /*!< 9 time quantum */ +#define CAN_BS1_10TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_0)) /*!< 10 time quantum */ +#define CAN_BS1_11TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1)) /*!< 11 time quantum */ +#define CAN_BS1_12TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 12 time quantum */ +#define CAN_BS1_13TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2)) /*!< 13 time quantum */ +#define CAN_BS1_14TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 14 time quantum */ +#define CAN_BS1_15TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 15 time quantum */ +#define CAN_BS1_16TQ ((uint32_t)CAN_BTR_TS1) /*!< 16 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_time_quantum_in_bit_segment_2 CAN Time Quantum in Bit Segment 2 + * @{ + */ +#define CAN_BS2_1TQ (0x00000000U) /*!< 1 time quantum */ +#define CAN_BS2_2TQ ((uint32_t)CAN_BTR_TS2_0) /*!< 2 time quantum */ +#define CAN_BS2_3TQ ((uint32_t)CAN_BTR_TS2_1) /*!< 3 time quantum */ +#define CAN_BS2_4TQ ((uint32_t)(CAN_BTR_TS2_1 | CAN_BTR_TS2_0)) /*!< 4 time quantum */ +#define CAN_BS2_5TQ ((uint32_t)CAN_BTR_TS2_2) /*!< 5 time quantum */ +#define CAN_BS2_6TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_0)) /*!< 6 time quantum */ +#define CAN_BS2_7TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_1)) /*!< 7 time quantum */ +#define CAN_BS2_8TQ ((uint32_t)CAN_BTR_TS2) /*!< 8 time quantum */ +/** + * @} + */ + +/** @defgroup CAN_filter_mode CAN Filter Mode + * @{ + */ +#define CAN_FILTERMODE_IDMASK (0x00000000U) /*!< Identifier mask mode */ +#define CAN_FILTERMODE_IDLIST (0x00000001U) /*!< Identifier list mode */ +/** + * @} + */ + +/** @defgroup CAN_filter_scale CAN Filter Scale + * @{ + */ +#define CAN_FILTERSCALE_16BIT (0x00000000U) /*!< Two 16-bit filters */ +#define CAN_FILTERSCALE_32BIT (0x00000001U) /*!< One 32-bit filter */ +/** + * @} + */ + +/** @defgroup CAN_filter_activation CAN Filter Activation + * @{ + */ +#define CAN_FILTER_DISABLE (0x00000000U) /*!< Disable filter */ +#define CAN_FILTER_ENABLE (0x00000001U) /*!< Enable filter */ +/** + * @} + */ + +/** @defgroup CAN_filter_FIFO CAN Filter FIFO + * @{ + */ +#define CAN_FILTER_FIFO0 (0x00000000U) /*!< Filter FIFO 0 assignment for filter x */ +#define CAN_FILTER_FIFO1 (0x00000001U) /*!< Filter FIFO 1 assignment for filter x */ +/** + * @} + */ + +/** @defgroup CAN_identifier_type CAN Identifier Type + * @{ + */ +#define CAN_ID_STD (0x00000000U) /*!< Standard Id */ +#define CAN_ID_EXT (0x00000004U) /*!< Extended Id */ +/** + * @} + */ + +/** @defgroup CAN_remote_transmission_request CAN Remote Transmission Request + * @{ + */ +#define CAN_RTR_DATA (0x00000000U) /*!< Data frame */ +#define CAN_RTR_REMOTE (0x00000002U) /*!< Remote frame */ +/** + * @} + */ + +/** @defgroup CAN_receive_FIFO_number CAN Receive FIFO Number + * @{ + */ +#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */ +#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */ +/** + * @} + */ + +/** @defgroup CAN_Tx_Mailboxes CAN Tx Mailboxes + * @{ + */ +#define CAN_TX_MAILBOX0 (0x00000001U) /*!< Tx Mailbox 0 */ +#define CAN_TX_MAILBOX1 (0x00000002U) /*!< Tx Mailbox 1 */ +#define CAN_TX_MAILBOX2 (0x00000004U) /*!< Tx Mailbox 2 */ +/** + * @} + */ + +/** @defgroup CAN_flags CAN Flags + * @{ + */ +/* Transmit Flags */ +#define CAN_FLAG_RQCP0 (0x00000500U) /*!< Request complete MailBox 0 flag */ +#define CAN_FLAG_TXOK0 (0x00000501U) /*!< Transmission OK MailBox 0 flag */ +#define CAN_FLAG_ALST0 (0x00000502U) /*!< Arbitration Lost MailBox 0 flag */ +#define CAN_FLAG_TERR0 (0x00000503U) /*!< Transmission error MailBox 0 flag */ +#define CAN_FLAG_RQCP1 (0x00000508U) /*!< Request complete MailBox1 flag */ +#define CAN_FLAG_TXOK1 (0x00000509U) /*!< Transmission OK MailBox 1 flag */ +#define CAN_FLAG_ALST1 (0x0000050AU) /*!< Arbitration Lost MailBox 1 flag */ +#define CAN_FLAG_TERR1 (0x0000050BU) /*!< Transmission error MailBox 1 flag */ +#define CAN_FLAG_RQCP2 (0x00000510U) /*!< Request complete MailBox2 flag */ +#define CAN_FLAG_TXOK2 (0x00000511U) /*!< Transmission OK MailBox 2 flag */ +#define CAN_FLAG_ALST2 (0x00000512U) /*!< Arbitration Lost MailBox 2 flag */ +#define CAN_FLAG_TERR2 (0x00000513U) /*!< Transmission error MailBox 2 flag */ +#define CAN_FLAG_TME0 (0x0000051AU) /*!< Transmit mailbox 0 empty flag */ +#define CAN_FLAG_TME1 (0x0000051BU) /*!< Transmit mailbox 1 empty flag */ +#define CAN_FLAG_TME2 (0x0000051CU) /*!< Transmit mailbox 2 empty flag */ +#define CAN_FLAG_LOW0 (0x0000051DU) /*!< Lowest priority mailbox 0 flag */ +#define CAN_FLAG_LOW1 (0x0000051EU) /*!< Lowest priority mailbox 1 flag */ +#define CAN_FLAG_LOW2 (0x0000051FU) /*!< Lowest priority mailbox 2 flag */ + +/* Receive Flags */ +#define CAN_FLAG_FF0 (0x00000203U) /*!< RX FIFO 0 Full flag */ +#define CAN_FLAG_FOV0 (0x00000204U) /*!< RX FIFO 0 Overrun flag */ +#define CAN_FLAG_FF1 (0x00000403U) /*!< RX FIFO 1 Full flag */ +#define CAN_FLAG_FOV1 (0x00000404U) /*!< RX FIFO 1 Overrun flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_INAK (0x00000100U) /*!< Initialization acknowledge flag */ +#define CAN_FLAG_SLAK (0x00000101U) /*!< Sleep acknowledge flag */ +#define CAN_FLAG_ERRI (0x00000102U) /*!< Error flag */ +#define CAN_FLAG_WKU (0x00000103U) /*!< Wake up interrupt flag */ +#define CAN_FLAG_SLAKI (0x00000104U) /*!< Sleep acknowledge interrupt flag */ + +/* Error Flags */ +#define CAN_FLAG_EWG (0x00000300U) /*!< Error warning flag */ +#define CAN_FLAG_EPV (0x00000301U) /*!< Error passive flag */ +#define CAN_FLAG_BOF (0x00000302U) /*!< Bus-Off flag */ +/** + * @} + */ + + +/** @defgroup CAN_Interrupts CAN Interrupts + * @{ + */ +/* Transmit Interrupt */ +#define CAN_IT_TX_MAILBOX_EMPTY ((uint32_t)CAN_IER_TMEIE) /*!< Transmit mailbox empty interrupt */ + +/* Receive Interrupts */ +#define CAN_IT_RX_FIFO0_MSG_PENDING ((uint32_t)CAN_IER_FMPIE0) /*!< FIFO 0 message pending interrupt */ +#define CAN_IT_RX_FIFO0_FULL ((uint32_t)CAN_IER_FFIE0) /*!< FIFO 0 full interrupt */ +#define CAN_IT_RX_FIFO0_OVERRUN ((uint32_t)CAN_IER_FOVIE0) /*!< FIFO 0 overrun interrupt */ +#define CAN_IT_RX_FIFO1_MSG_PENDING ((uint32_t)CAN_IER_FMPIE1) /*!< FIFO 1 message pending interrupt */ +#define CAN_IT_RX_FIFO1_FULL ((uint32_t)CAN_IER_FFIE1) /*!< FIFO 1 full interrupt */ +#define CAN_IT_RX_FIFO1_OVERRUN ((uint32_t)CAN_IER_FOVIE1) /*!< FIFO 1 overrun interrupt */ + +/* Operating Mode Interrupts */ +#define CAN_IT_WAKEUP ((uint32_t)CAN_IER_WKUIE) /*!< Wake-up interrupt */ +#define CAN_IT_SLEEP_ACK ((uint32_t)CAN_IER_SLKIE) /*!< Sleep acknowledge interrupt */ + +/* Error Interrupts */ +#define CAN_IT_ERROR_WARNING ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt */ +#define CAN_IT_ERROR_PASSIVE ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt */ +#define CAN_IT_BUSOFF ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt */ +#define CAN_IT_LAST_ERROR_CODE ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */ +#define CAN_IT_ERROR ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CAN_Exported_Macros CAN Exported Macros + * @{ + */ + +/** @brief Reset CAN handle state + * @param __HANDLE__ CAN handle. + * @retval None + */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 +#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_CAN_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CAN_STATE_RESET) +#endif /*USE_HAL_CAN_REGISTER_CALLBACKS */ + +/** + * @brief Enable the specified CAN interrupts. + * @param __HANDLE__ CAN handle. + * @param __INTERRUPT__ CAN Interrupt sources to enable. + * This parameter can be any combination of @arg CAN_Interrupts + * @retval None + */ +#define __HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) |= (__INTERRUPT__)) + +/** + * @brief Disable the specified CAN interrupts. + * @param __HANDLE__ CAN handle. + * @param __INTERRUPT__ CAN Interrupt sources to disable. + * This parameter can be any combination of @arg CAN_Interrupts + * @retval None + */ +#define __HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) &= ~(__INTERRUPT__)) + +/** @brief Check if the specified CAN interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the CAN Handle. + * @param __INTERRUPT__ specifies the CAN interrupt source to check. + * This parameter can be a value of @arg CAN_Interrupts + * @retval The state of __IT__ (TRUE or FALSE). + */ +#define __HAL_CAN_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) & (__INTERRUPT__)) + +/** @brief Check whether the specified CAN flag is set or not. + * @param __HANDLE__ specifies the CAN Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of @arg CAN_flags + * @retval The state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_CAN_GET_FLAG(__HANDLE__, __FLAG__) \ + ((((__FLAG__) >> 8U) == 5U)? ((((__HANDLE__)->Instance->TSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 2U)? ((((__HANDLE__)->Instance->RF0R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 4U)? ((((__HANDLE__)->Instance->RF1R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 1U)? ((((__HANDLE__)->Instance->MSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 3U)? ((((__HANDLE__)->Instance->ESR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U) + +/** @brief Clear the specified CAN pending flag. + * @param __HANDLE__ specifies the CAN Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg CAN_FLAG_RQCP0: Request complete MailBox 0 Flag + * @arg CAN_FLAG_TXOK0: Transmission OK MailBox 0 Flag + * @arg CAN_FLAG_ALST0: Arbitration Lost MailBox 0 Flag + * @arg CAN_FLAG_TERR0: Transmission error MailBox 0 Flag + * @arg CAN_FLAG_RQCP1: Request complete MailBox 1 Flag + * @arg CAN_FLAG_TXOK1: Transmission OK MailBox 1 Flag + * @arg CAN_FLAG_ALST1: Arbitration Lost MailBox 1 Flag + * @arg CAN_FLAG_TERR1: Transmission error MailBox 1 Flag + * @arg CAN_FLAG_RQCP2: Request complete MailBox 2 Flag + * @arg CAN_FLAG_TXOK2: Transmission OK MailBox 2 Flag + * @arg CAN_FLAG_ALST2: Arbitration Lost MailBox 2 Flag + * @arg CAN_FLAG_TERR2: Transmission error MailBox 2 Flag + * @arg CAN_FLAG_FF0: RX FIFO 0 Full Flag + * @arg CAN_FLAG_FOV0: RX FIFO 0 Overrun Flag + * @arg CAN_FLAG_FF1: RX FIFO 1 Full Flag + * @arg CAN_FLAG_FOV1: RX FIFO 1 Overrun Flag + * @arg CAN_FLAG_WKUI: Wake up Interrupt Flag + * @arg CAN_FLAG_SLAKI: Sleep acknowledge Interrupt Flag + * @retval None + */ +#define __HAL_CAN_CLEAR_FLAG(__HANDLE__, __FLAG__) \ + ((((__FLAG__) >> 8U) == 5U)? (((__HANDLE__)->Instance->TSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 2U)? (((__HANDLE__)->Instance->RF0R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 4U)? (((__HANDLE__)->Instance->RF1R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \ + (((__FLAG__) >> 8U) == 1U)? (((__HANDLE__)->Instance->MSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup CAN_Exported_Functions CAN Exported Functions + * @{ + */ + +/** @addtogroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * @{ + */ + +/* Initialization and de-initialization functions *****************************/ +HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan); +void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan); +void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan); + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 +/* Callbacks Register/UnRegister functions ***********************************/ +HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID, + void (* pCallback)(CAN_HandleTypeDef *_hcan)); +HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID); + +#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group2 Configuration functions + * @brief Configuration functions + * @{ + */ + +/* Configuration functions ****************************************************/ +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig); + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group3 Control functions + * @brief Control functions + * @{ + */ + +/* Control functions **********************************************************/ +HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan); +uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader, + const uint8_t aData[], uint32_t *pTxMailbox); +HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes); +uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan); +uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes); +uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox); +HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, + CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]); +uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo); + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group4 Interrupts management + * @brief Interrupts management + * @{ + */ +/* Interrupts management ******************************************************/ +HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs); +HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs); +void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan); + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group5 Callback functions + * @brief Callback functions + * @{ + */ +/* Callbacks functions ********************************************************/ + +void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan); +void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan); + +/** + * @} + */ + +/** @addtogroup CAN_Exported_Functions_Group6 Peripheral State and Error functions + * @brief CAN Peripheral State functions + * @{ + */ +/* Peripheral State and Error functions ***************************************/ +HAL_CAN_StateTypeDef HAL_CAN_GetState(const CAN_HandleTypeDef *hcan); +uint32_t HAL_CAN_GetError(const CAN_HandleTypeDef *hcan); +HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan); + +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup CAN_Private_Types CAN Private Types + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup CAN_Private_Variables CAN Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup CAN_Private_Constants CAN Private Constants + * @{ + */ +#define CAN_FLAG_MASK (0x000000FFU) +/** + * @} + */ + +/* Private Macros -----------------------------------------------------------*/ +/** @defgroup CAN_Private_Macros CAN Private Macros + * @{ + */ + +#define IS_CAN_MODE(MODE) (((MODE) == CAN_MODE_NORMAL) || \ + ((MODE) == CAN_MODE_LOOPBACK)|| \ + ((MODE) == CAN_MODE_SILENT) || \ + ((MODE) == CAN_MODE_SILENT_LOOPBACK)) +#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1TQ) || ((SJW) == CAN_SJW_2TQ) || \ + ((SJW) == CAN_SJW_3TQ) || ((SJW) == CAN_SJW_4TQ)) +#define IS_CAN_BS1(BS1) (((BS1) == CAN_BS1_1TQ) || ((BS1) == CAN_BS1_2TQ) || \ + ((BS1) == CAN_BS1_3TQ) || ((BS1) == CAN_BS1_4TQ) || \ + ((BS1) == CAN_BS1_5TQ) || ((BS1) == CAN_BS1_6TQ) || \ + ((BS1) == CAN_BS1_7TQ) || ((BS1) == CAN_BS1_8TQ) || \ + ((BS1) == CAN_BS1_9TQ) || ((BS1) == CAN_BS1_10TQ)|| \ + ((BS1) == CAN_BS1_11TQ)|| ((BS1) == CAN_BS1_12TQ)|| \ + ((BS1) == CAN_BS1_13TQ)|| ((BS1) == CAN_BS1_14TQ)|| \ + ((BS1) == CAN_BS1_15TQ)|| ((BS1) == CAN_BS1_16TQ)) +#define IS_CAN_BS2(BS2) (((BS2) == CAN_BS2_1TQ) || ((BS2) == CAN_BS2_2TQ) || \ + ((BS2) == CAN_BS2_3TQ) || ((BS2) == CAN_BS2_4TQ) || \ + ((BS2) == CAN_BS2_5TQ) || ((BS2) == CAN_BS2_6TQ) || \ + ((BS2) == CAN_BS2_7TQ) || ((BS2) == CAN_BS2_8TQ)) +#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1U) && ((PRESCALER) <= 1024U)) +#define IS_CAN_FILTER_ID_HALFWORD(HALFWORD) ((HALFWORD) <= 0xFFFFU) +#define IS_CAN_FILTER_BANK_DUAL(BANK) ((BANK) <= 27U) +#define IS_CAN_FILTER_BANK_SINGLE(BANK) ((BANK) <= 13U) +#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FILTERMODE_IDMASK) || \ + ((MODE) == CAN_FILTERMODE_IDLIST)) +#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FILTERSCALE_16BIT) || \ + ((SCALE) == CAN_FILTERSCALE_32BIT)) +#define IS_CAN_FILTER_ACTIVATION(ACTIVATION) (((ACTIVATION) == CAN_FILTER_DISABLE) || \ + ((ACTIVATION) == CAN_FILTER_ENABLE)) +#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FILTER_FIFO0) || \ + ((FIFO) == CAN_FILTER_FIFO1)) +#define IS_CAN_TX_MAILBOX(TRANSMITMAILBOX) (((TRANSMITMAILBOX) == CAN_TX_MAILBOX0 ) || \ + ((TRANSMITMAILBOX) == CAN_TX_MAILBOX1 ) || \ + ((TRANSMITMAILBOX) == CAN_TX_MAILBOX2 )) +#define IS_CAN_TX_MAILBOX_LIST(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= (CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | \ + CAN_TX_MAILBOX2)) +#define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU) +#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU) +#define IS_CAN_DLC(DLC) ((DLC) <= 8U) +#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_ID_STD) || \ + ((IDTYPE) == CAN_ID_EXT)) +#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_DATA) || ((RTR) == CAN_RTR_REMOTE)) +#define IS_CAN_RX_FIFO(FIFO) (((FIFO) == CAN_RX_FIFO0) || ((FIFO) == CAN_RX_FIFO1)) +#define IS_CAN_IT(IT) ((IT) <= (CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING | \ + CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO0_OVERRUN | \ + CAN_IT_RX_FIFO1_MSG_PENDING | CAN_IT_RX_FIFO1_FULL | \ + CAN_IT_RX_FIFO1_OVERRUN | CAN_IT_WAKEUP | \ + CAN_IT_SLEEP_ACK | CAN_IT_ERROR_WARNING | \ + CAN_IT_ERROR_PASSIVE | CAN_IT_BUSOFF | \ + CAN_IT_LAST_ERROR_CODE | CAN_IT_ERROR)) + +/** + * @} + */ +/* End of private macros -----------------------------------------------------*/ + +/** + * @} + */ + + +#endif /* CAN1 */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_CAN_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h new file mode 100644 index 0000000..7738946 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cec.h @@ -0,0 +1,792 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cec.h + * @author MCD Application Team + * @brief Header file of CEC 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 STM32F4xx_HAL_CEC_H +#define STM32F4xx_HAL_CEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined (CEC) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CEC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CEC_Exported_Types CEC Exported Types + * @{ + */ + +/** + * @brief CEC Init Structure definition + */ +typedef struct +{ + uint32_t SignalFreeTime; /*!< Set SFT field, specifies the Signal Free Time. + It can be one of @ref CEC_Signal_Free_Time + and belongs to the set {0,...,7} where + 0x0 is the default configuration + else means 0.5 + (SignalFreeTime - 1) nominal data bit periods */ + + uint32_t Tolerance; /*!< Set RXTOL bit, specifies the tolerance accepted on the received waveforms, + it can be a value of @ref CEC_Tolerance : it is either CEC_STANDARD_TOLERANCE + or CEC_EXTENDED_TOLERANCE */ + + uint32_t BRERxStop; /*!< Set BRESTP bit @ref CEC_BRERxStop : specifies whether or not a Bit Rising Error stops the reception. + CEC_NO_RX_STOP_ON_BRE: reception is not stopped. + CEC_RX_STOP_ON_BRE: reception is stopped. */ + + uint32_t BREErrorBitGen; /*!< Set BREGEN bit @ref CEC_BREErrorBitGen : specifies whether or not an Error-Bit is generated on the + CEC line upon Bit Rising Error detection. + CEC_BRE_ERRORBIT_NO_GENERATION: no error-bit generation. + CEC_BRE_ERRORBIT_GENERATION: error-bit generation if BRESTP is set. */ + + uint32_t LBPEErrorBitGen; /*!< Set LBPEGEN bit @ref CEC_LBPEErrorBitGen : specifies whether or not an Error-Bit is generated on the + CEC line upon Long Bit Period Error detection. + CEC_LBPE_ERRORBIT_NO_GENERATION: no error-bit generation. + CEC_LBPE_ERRORBIT_GENERATION: error-bit generation. */ + + uint32_t BroadcastMsgNoErrorBitGen; /*!< Set BRDNOGEN bit @ref CEC_BroadCastMsgErrorBitGen : allows to avoid an Error-Bit generation on the CEC line + upon an error detected on a broadcast message. + + It supersedes BREGEN and LBPEGEN bits for a broadcast message error handling. It can take two values: + + 1) CEC_BROADCASTERROR_ERRORBIT_GENERATION. + a) BRE detection: error-bit generation on the CEC line if BRESTP=CEC_RX_STOP_ON_BRE + and BREGEN=CEC_BRE_ERRORBIT_NO_GENERATION. + b) LBPE detection: error-bit generation on the CEC line + if LBPGEN=CEC_LBPE_ERRORBIT_NO_GENERATION. + + 2) CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION. + no error-bit generation in case neither a) nor b) are satisfied. Additionally, + there is no error-bit generation in case of Short Bit Period Error detection in + a broadcast message while LSTN bit is set. */ + + uint32_t SignalFreeTimeOption; /*!< Set SFTOP bit @ref CEC_SFT_Option : specifies when SFT timer starts. + CEC_SFT_START_ON_TXSOM SFT: timer starts when TXSOM is set by software. + CEC_SFT_START_ON_TX_RX_END: SFT timer starts automatically at the end of message transmission/reception. */ + + uint32_t ListenMode; /*!< Set LSTN bit @ref CEC_Listening_Mode : specifies device listening mode. It can take two values: + + CEC_REDUCED_LISTENING_MODE: CEC peripheral receives only message addressed to its + own address (OAR). Messages addressed to different destination are ignored. + Broadcast messages are always received. + + CEC_FULL_LISTENING_MODE: CEC peripheral receives messages addressed to its own + address (OAR) with positive acknowledge. Messages addressed to different destination + are received, but without interfering with the CEC bus: no acknowledge sent. */ + + uint16_t OwnAddress; /*!< Own addresses configuration + This parameter can be a value of @ref CEC_OWN_ADDRESS */ + + uint8_t *RxBuffer; /*!< CEC Rx buffer pointer */ + + +} CEC_InitTypeDef; + +/** + * @brief HAL CEC State definition + * @note HAL CEC State value is a combination of 2 different substates: gState and RxState (see @ref CEC_State_Definition). + * - gState contains CEC state information related to global Handle management + * and also information related to Tx operations. + * gState value coding follow below described bitmap : + * b7 (not used) + * x : Should be set to 0 + * b6 Error information + * 0 : No Error + * 1 : Error + * b5 CEC peripheral initialization status + * 0 : Reset (peripheral not initialized) + * 1 : Init done (peripheral initialized. HAL CEC 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 CEC 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 uint32_t HAL_CEC_StateTypeDef; + +/** + * @brief CEC handle Structure definition + */ +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +typedef struct __CEC_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ +{ + CEC_TypeDef *Instance; /*!< CEC registers base address */ + + CEC_InitTypeDef Init; /*!< CEC communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to CEC Tx transfer Buffer */ + + uint16_t TxXferCount; /*!< CEC Tx Transfer Counter */ + + uint16_t RxXferSize; /*!< CEC Rx Transfer size, 0: header received only */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + HAL_CEC_StateTypeDef gState; /*!< CEC state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_CEC_StateTypeDef */ + + HAL_CEC_StateTypeDef RxState; /*!< CEC state information related to Rx operations. + This parameter can be a value of @ref HAL_CEC_StateTypeDef */ + + uint32_t ErrorCode; /*!< For errors handling purposes, copy of ISR register + in case error is reported */ + +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) + void (* TxCpltCallback)(struct __CEC_HandleTypeDef + *hcec); /*!< CEC Tx Transfer completed callback */ + void (* RxCpltCallback)(struct __CEC_HandleTypeDef *hcec, + uint32_t RxFrameSize); /*!< CEC Rx Transfer completed callback */ + void (* ErrorCallback)(struct __CEC_HandleTypeDef *hcec); /*!< CEC error callback */ + + void (* MspInitCallback)(struct __CEC_HandleTypeDef *hcec); /*!< CEC Msp Init callback */ + void (* MspDeInitCallback)(struct __CEC_HandleTypeDef *hcec); /*!< CEC Msp DeInit callback */ + +#endif /* (USE_HAL_CEC_REGISTER_CALLBACKS) */ +} CEC_HandleTypeDef; + +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +/** + * @brief HAL CEC Callback ID enumeration definition + */ +typedef enum +{ + HAL_CEC_TX_CPLT_CB_ID = 0x00U, /*!< CEC Tx Transfer completed callback ID */ + HAL_CEC_RX_CPLT_CB_ID = 0x01U, /*!< CEC Rx Transfer completed callback ID */ + HAL_CEC_ERROR_CB_ID = 0x02U, /*!< CEC error callback ID */ + HAL_CEC_MSPINIT_CB_ID = 0x03U, /*!< CEC Msp Init callback ID */ + HAL_CEC_MSPDEINIT_CB_ID = 0x04U /*!< CEC Msp DeInit callback ID */ +} HAL_CEC_CallbackIDTypeDef; + +/** + * @brief HAL CEC Callback pointer definition + */ +typedef void (*pCEC_CallbackTypeDef)(CEC_HandleTypeDef *hcec); /*!< pointer to an CEC callback function */ +typedef void (*pCEC_RxCallbackTypeDef)(CEC_HandleTypeDef *hcec, + uint32_t RxFrameSize); /*!< pointer to an Rx Transfer completed callback function */ +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CEC_Exported_Constants CEC Exported Constants + * @{ + */ +/** @defgroup CEC_State_Definition CEC State Code Definition + * @{ + */ +#define HAL_CEC_STATE_RESET ((uint32_t)0x00000000) /*!< Peripheral is not yet Initialized + Value is allowed for gState and RxState */ +#define HAL_CEC_STATE_READY ((uint32_t)0x00000020) /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ +#define HAL_CEC_STATE_BUSY ((uint32_t)0x00000024) /*!< an internal process is ongoing + Value is allowed for gState only */ +#define HAL_CEC_STATE_BUSY_RX ((uint32_t)0x00000022) /*!< Data Reception process is ongoing + Value is allowed for RxState only */ +#define HAL_CEC_STATE_BUSY_TX ((uint32_t)0x00000021) /*!< Data Transmission process is ongoing + Value is allowed for gState only */ +#define HAL_CEC_STATE_BUSY_RX_TX ((uint32_t)0x00000023) /*!< an internal process is ongoing + Value is allowed for gState only */ +#define HAL_CEC_STATE_ERROR ((uint32_t)0x00000050) /*!< Error Value is allowed for gState only */ +/** + * @} + */ +/** @defgroup CEC_Error_Code CEC Error Code + * @{ + */ +#define HAL_CEC_ERROR_NONE (uint32_t) 0x0000U /*!< no error */ +#define HAL_CEC_ERROR_RXOVR CEC_ISR_RXOVR /*!< CEC Rx-Overrun */ +#define HAL_CEC_ERROR_BRE CEC_ISR_BRE /*!< CEC Rx Bit Rising Error */ +#define HAL_CEC_ERROR_SBPE CEC_ISR_SBPE /*!< CEC Rx Short Bit period Error */ +#define HAL_CEC_ERROR_LBPE CEC_ISR_LBPE /*!< CEC Rx Long Bit period Error */ +#define HAL_CEC_ERROR_RXACKE CEC_ISR_RXACKE /*!< CEC Rx Missing Acknowledge */ +#define HAL_CEC_ERROR_ARBLST CEC_ISR_ARBLST /*!< CEC Arbitration Lost */ +#define HAL_CEC_ERROR_TXUDR CEC_ISR_TXUDR /*!< CEC Tx-Buffer Underrun */ +#define HAL_CEC_ERROR_TXERR CEC_ISR_TXERR /*!< CEC Tx-Error */ +#define HAL_CEC_ERROR_TXACKE CEC_ISR_TXACKE /*!< CEC Tx Missing Acknowledge */ +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +#define HAL_CEC_ERROR_INVALID_CALLBACK ((uint32_t)0x00002000U) /*!< Invalid Callback Error */ +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup CEC_Signal_Free_Time CEC Signal Free Time setting parameter + * @{ + */ +#define CEC_DEFAULT_SFT ((uint32_t)0x00000000U) +#define CEC_0_5_BITPERIOD_SFT ((uint32_t)0x00000001U) +#define CEC_1_5_BITPERIOD_SFT ((uint32_t)0x00000002U) +#define CEC_2_5_BITPERIOD_SFT ((uint32_t)0x00000003U) +#define CEC_3_5_BITPERIOD_SFT ((uint32_t)0x00000004U) +#define CEC_4_5_BITPERIOD_SFT ((uint32_t)0x00000005U) +#define CEC_5_5_BITPERIOD_SFT ((uint32_t)0x00000006U) +#define CEC_6_5_BITPERIOD_SFT ((uint32_t)0x00000007U) +/** + * @} + */ + +/** @defgroup CEC_Tolerance CEC Receiver Tolerance + * @{ + */ +#define CEC_STANDARD_TOLERANCE ((uint32_t)0x00000000U) +#define CEC_EXTENDED_TOLERANCE ((uint32_t)CEC_CFGR_RXTOL) +/** + * @} + */ + +/** @defgroup CEC_BRERxStop CEC Reception Stop on Error + * @{ + */ +#define CEC_NO_RX_STOP_ON_BRE ((uint32_t)0x00000000U) +#define CEC_RX_STOP_ON_BRE ((uint32_t)CEC_CFGR_BRESTP) +/** + * @} + */ + +/** @defgroup CEC_BREErrorBitGen CEC Error Bit Generation if Bit Rise Error reported + * @{ + */ +#define CEC_BRE_ERRORBIT_NO_GENERATION ((uint32_t)0x00000000U) +#define CEC_BRE_ERRORBIT_GENERATION ((uint32_t)CEC_CFGR_BREGEN) +/** + * @} + */ + +/** @defgroup CEC_LBPEErrorBitGen CEC Error Bit Generation if Long Bit Period Error reported + * @{ + */ +#define CEC_LBPE_ERRORBIT_NO_GENERATION ((uint32_t)0x00000000U) +#define CEC_LBPE_ERRORBIT_GENERATION ((uint32_t)CEC_CFGR_LBPEGEN) +/** + * @} + */ + +/** @defgroup CEC_BroadCastMsgErrorBitGen CEC Error Bit Generation on Broadcast message + * @{ + */ +#define CEC_BROADCASTERROR_ERRORBIT_GENERATION ((uint32_t)0x00000000U) +#define CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION ((uint32_t)CEC_CFGR_BRDNOGEN) +/** + * @} + */ + +/** @defgroup CEC_SFT_Option CEC Signal Free Time start option + * @{ + */ +#define CEC_SFT_START_ON_TXSOM ((uint32_t)0x00000000U) +#define CEC_SFT_START_ON_TX_RX_END ((uint32_t)CEC_CFGR_SFTOPT) +/** + * @} + */ + +/** @defgroup CEC_Listening_Mode CEC Listening mode option + * @{ + */ +#define CEC_REDUCED_LISTENING_MODE ((uint32_t)0x00000000U) +#define CEC_FULL_LISTENING_MODE ((uint32_t)CEC_CFGR_LSTN) +/** + * @} + */ + +/** @defgroup CEC_OAR_Position CEC Device Own Address position in CEC CFGR register + * @{ + */ +#define CEC_CFGR_OAR_LSB_POS ((uint32_t) 16U) +/** + * @} + */ + +/** @defgroup CEC_Initiator_Position CEC Initiator logical address position in message header + * @{ + */ +#define CEC_INITIATOR_LSB_POS ((uint32_t) 4U) +/** + * @} + */ + +/** @defgroup CEC_OWN_ADDRESS CEC Own Address + * @{ + */ +#define CEC_OWN_ADDRESS_NONE ((uint16_t) 0x0000U) /* Reset value */ +#define CEC_OWN_ADDRESS_0 ((uint16_t) 0x0001U) /* Logical Address 0 */ +#define CEC_OWN_ADDRESS_1 ((uint16_t) 0x0002U) /* Logical Address 1 */ +#define CEC_OWN_ADDRESS_2 ((uint16_t) 0x0004U) /* Logical Address 2 */ +#define CEC_OWN_ADDRESS_3 ((uint16_t) 0x0008U) /* Logical Address 3 */ +#define CEC_OWN_ADDRESS_4 ((uint16_t) 0x0010U) /* Logical Address 4 */ +#define CEC_OWN_ADDRESS_5 ((uint16_t) 0x0020U) /* Logical Address 5 */ +#define CEC_OWN_ADDRESS_6 ((uint16_t) 0x0040U) /* Logical Address 6 */ +#define CEC_OWN_ADDRESS_7 ((uint16_t) 0x0080U) /* Logical Address 7 */ +#define CEC_OWN_ADDRESS_8 ((uint16_t) 0x0100U) /* Logical Address 9 */ +#define CEC_OWN_ADDRESS_9 ((uint16_t) 0x0200U) /* Logical Address 10 */ +#define CEC_OWN_ADDRESS_10 ((uint16_t) 0x0400U) /* Logical Address 11 */ +#define CEC_OWN_ADDRESS_11 ((uint16_t) 0x0800U) /* Logical Address 12 */ +#define CEC_OWN_ADDRESS_12 ((uint16_t) 0x1000U) /* Logical Address 13 */ +#define CEC_OWN_ADDRESS_13 ((uint16_t) 0x2000U) /* Logical Address 14 */ +#define CEC_OWN_ADDRESS_14 ((uint16_t) 0x4000U) /* Logical Address 15 */ +/** + * @} + */ + +/** @defgroup CEC_Interrupts_Definitions CEC Interrupts definition + * @{ + */ +#define CEC_IT_TXACKE CEC_IER_TXACKEIE +#define CEC_IT_TXERR CEC_IER_TXERRIE +#define CEC_IT_TXUDR CEC_IER_TXUDRIE +#define CEC_IT_TXEND CEC_IER_TXENDIE +#define CEC_IT_TXBR CEC_IER_TXBRIE +#define CEC_IT_ARBLST CEC_IER_ARBLSTIE +#define CEC_IT_RXACKE CEC_IER_RXACKEIE +#define CEC_IT_LBPE CEC_IER_LBPEIE +#define CEC_IT_SBPE CEC_IER_SBPEIE +#define CEC_IT_BRE CEC_IER_BREIE +#define CEC_IT_RXOVR CEC_IER_RXOVRIE +#define CEC_IT_RXEND CEC_IER_RXENDIE +#define CEC_IT_RXBR CEC_IER_RXBRIE +/** + * @} + */ + +/** @defgroup CEC_Flags_Definitions CEC Flags definition + * @{ + */ +#define CEC_FLAG_TXACKE CEC_ISR_TXACKE +#define CEC_FLAG_TXERR CEC_ISR_TXERR +#define CEC_FLAG_TXUDR CEC_ISR_TXUDR +#define CEC_FLAG_TXEND CEC_ISR_TXEND +#define CEC_FLAG_TXBR CEC_ISR_TXBR +#define CEC_FLAG_ARBLST CEC_ISR_ARBLST +#define CEC_FLAG_RXACKE CEC_ISR_RXACKE +#define CEC_FLAG_LBPE CEC_ISR_LBPE +#define CEC_FLAG_SBPE CEC_ISR_SBPE +#define CEC_FLAG_BRE CEC_ISR_BRE +#define CEC_FLAG_RXOVR CEC_ISR_RXOVR +#define CEC_FLAG_RXEND CEC_ISR_RXEND +#define CEC_FLAG_RXBR CEC_ISR_RXBR +/** + * @} + */ + +/** @defgroup CEC_ALL_ERROR CEC all RX or TX errors flags + * @{ + */ +#define CEC_ISR_ALL_ERROR ((uint32_t)CEC_ISR_RXOVR|CEC_ISR_BRE|CEC_ISR_SBPE|CEC_ISR_LBPE|CEC_ISR_RXACKE|\ + CEC_ISR_ARBLST|CEC_ISR_TXUDR|CEC_ISR_TXERR|CEC_ISR_TXACKE) +/** + * @} + */ + +/** @defgroup CEC_IER_ALL_RX CEC all RX errors interrupts enabling flag + * @{ + */ +#define CEC_IER_RX_ALL_ERR ((uint32_t)CEC_IER_RXACKEIE|CEC_IER_LBPEIE|CEC_IER_SBPEIE|CEC_IER_BREIE|CEC_IER_RXOVRIE) +/** + * @} + */ + +/** @defgroup CEC_IER_ALL_TX CEC all TX errors interrupts enabling flag + * @{ + */ +#define CEC_IER_TX_ALL_ERR ((uint32_t)CEC_IER_TXACKEIE|CEC_IER_TXERRIE|CEC_IER_TXUDRIE|CEC_IER_ARBLSTIE) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CEC_Exported_Macros CEC Exported Macros + * @{ + */ + +/** @brief Reset CEC handle gstate & RxState + * @param __HANDLE__ CEC handle. + * @retval None + */ +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +#define __HAL_CEC_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_CEC_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_CEC_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_CEC_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_CEC_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_CEC_STATE_RESET; \ + } while(0) +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ +/** @brief Checks whether or not the specified CEC interrupt flag is set. + * @param __HANDLE__ specifies the CEC Handle. + * @param __FLAG__ specifies the flag to check. + * @arg CEC_FLAG_TXACKE: Tx Missing acknowledge Error + * @arg CEC_FLAG_TXERR: Tx Error. + * @arg CEC_FLAG_TXUDR: Tx-Buffer Underrun. + * @arg CEC_FLAG_TXEND: End of transmission (successful transmission of the last byte). + * @arg CEC_FLAG_TXBR: Tx-Byte Request. + * @arg CEC_FLAG_ARBLST: Arbitration Lost + * @arg CEC_FLAG_RXACKE: Rx-Missing Acknowledge + * @arg CEC_FLAG_LBPE: Rx Long period Error + * @arg CEC_FLAG_SBPE: Rx Short period Error + * @arg CEC_FLAG_BRE: Rx Bit Rising Error + * @arg CEC_FLAG_RXOVR: Rx Overrun. + * @arg CEC_FLAG_RXEND: End Of Reception. + * @arg CEC_FLAG_RXBR: Rx-Byte Received. + * @retval ITStatus + */ +#define __HAL_CEC_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR & (__FLAG__)) + +/** @brief Clears the interrupt or status flag when raised (write at 1) + * @param __HANDLE__ specifies the CEC Handle. + * @param __FLAG__ specifies the interrupt/status flag to clear. + * This parameter can be one of the following values: + * @arg CEC_FLAG_TXACKE: Tx Missing acknowledge Error + * @arg CEC_FLAG_TXERR: Tx Error. + * @arg CEC_FLAG_TXUDR: Tx-Buffer Underrun. + * @arg CEC_FLAG_TXEND: End of transmission (successful transmission of the last byte). + * @arg CEC_FLAG_TXBR: Tx-Byte Request. + * @arg CEC_FLAG_ARBLST: Arbitration Lost + * @arg CEC_FLAG_RXACKE: Rx-Missing Acknowledge + * @arg CEC_FLAG_LBPE: Rx Long period Error + * @arg CEC_FLAG_SBPE: Rx Short period Error + * @arg CEC_FLAG_BRE: Rx Bit Rising Error + * @arg CEC_FLAG_RXOVR: Rx Overrun. + * @arg CEC_FLAG_RXEND: End Of Reception. + * @arg CEC_FLAG_RXBR: Rx-Byte Received. + * @retval none + */ +#define __HAL_CEC_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR |= (__FLAG__)) + +/** @brief Enables the specified CEC interrupt. + * @param __HANDLE__ specifies the CEC Handle. + * @param __INTERRUPT__ specifies the CEC interrupt to enable. + * This parameter can be one of the following values: + * @arg CEC_IT_TXACKE: Tx Missing acknowledge Error IT Enable + * @arg CEC_IT_TXERR: Tx Error IT Enable + * @arg CEC_IT_TXUDR: Tx-Buffer Underrun IT Enable + * @arg CEC_IT_TXEND: End of transmission IT Enable + * @arg CEC_IT_TXBR: Tx-Byte Request IT Enable + * @arg CEC_IT_ARBLST: Arbitration Lost IT Enable + * @arg CEC_IT_RXACKE: Rx-Missing Acknowledge IT Enable + * @arg CEC_IT_LBPE: Rx Long period Error IT Enable + * @arg CEC_IT_SBPE: Rx Short period Error IT Enable + * @arg CEC_IT_BRE: Rx Bit Rising Error IT Enable + * @arg CEC_IT_RXOVR: Rx Overrun IT Enable + * @arg CEC_IT_RXEND: End Of Reception IT Enable + * @arg CEC_IT_RXBR: Rx-Byte Received IT Enable + * @retval none + */ +#define __HAL_CEC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER |= (__INTERRUPT__)) + +/** @brief Disables the specified CEC interrupt. + * @param __HANDLE__ specifies the CEC Handle. + * @param __INTERRUPT__ specifies the CEC interrupt to disable. + * This parameter can be one of the following values: + * @arg CEC_IT_TXACKE: Tx Missing acknowledge Error IT Enable + * @arg CEC_IT_TXERR: Tx Error IT Enable + * @arg CEC_IT_TXUDR: Tx-Buffer Underrun IT Enable + * @arg CEC_IT_TXEND: End of transmission IT Enable + * @arg CEC_IT_TXBR: Tx-Byte Request IT Enable + * @arg CEC_IT_ARBLST: Arbitration Lost IT Enable + * @arg CEC_IT_RXACKE: Rx-Missing Acknowledge IT Enable + * @arg CEC_IT_LBPE: Rx Long period Error IT Enable + * @arg CEC_IT_SBPE: Rx Short period Error IT Enable + * @arg CEC_IT_BRE: Rx Bit Rising Error IT Enable + * @arg CEC_IT_RXOVR: Rx Overrun IT Enable + * @arg CEC_IT_RXEND: End Of Reception IT Enable + * @arg CEC_IT_RXBR: Rx-Byte Received IT Enable + * @retval none + */ +#define __HAL_CEC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER &= (~(__INTERRUPT__))) + +/** @brief Checks whether or not the specified CEC interrupt is enabled. + * @param __HANDLE__ specifies the CEC Handle. + * @param __INTERRUPT__ specifies the CEC interrupt to check. + * This parameter can be one of the following values: + * @arg CEC_IT_TXACKE: Tx Missing acknowledge Error IT Enable + * @arg CEC_IT_TXERR: Tx Error IT Enable + * @arg CEC_IT_TXUDR: Tx-Buffer Underrun IT Enable + * @arg CEC_IT_TXEND: End of transmission IT Enable + * @arg CEC_IT_TXBR: Tx-Byte Request IT Enable + * @arg CEC_IT_ARBLST: Arbitration Lost IT Enable + * @arg CEC_IT_RXACKE: Rx-Missing Acknowledge IT Enable + * @arg CEC_IT_LBPE: Rx Long period Error IT Enable + * @arg CEC_IT_SBPE: Rx Short period Error IT Enable + * @arg CEC_IT_BRE: Rx Bit Rising Error IT Enable + * @arg CEC_IT_RXOVR: Rx Overrun IT Enable + * @arg CEC_IT_RXEND: End Of Reception IT Enable + * @arg CEC_IT_RXBR: Rx-Byte Received IT Enable + * @retval FlagStatus + */ +#define __HAL_CEC_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER & (__INTERRUPT__)) + +/** @brief Enables the CEC device + * @param __HANDLE__ specifies the CEC Handle. + * @retval none + */ +#define __HAL_CEC_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= CEC_CR_CECEN) + +/** @brief Disables the CEC device + * @param __HANDLE__ specifies the CEC Handle. + * @retval none + */ +#define __HAL_CEC_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~CEC_CR_CECEN) + +/** @brief Set Transmission Start flag + * @param __HANDLE__ specifies the CEC Handle. + * @retval none + */ +#define __HAL_CEC_FIRST_BYTE_TX_SET(__HANDLE__) ((__HANDLE__)->Instance->CR |= CEC_CR_TXSOM) + +/** @brief Set Transmission End flag + * @param __HANDLE__ specifies the CEC Handle. + * @retval none + * If the CEC message consists of only one byte, TXEOM must be set before of TXSOM. + */ +#define __HAL_CEC_LAST_BYTE_TX_SET(__HANDLE__) ((__HANDLE__)->Instance->CR |= CEC_CR_TXEOM) + +/** @brief Get Transmission Start flag + * @param __HANDLE__ specifies the CEC Handle. + * @retval FlagStatus + */ +#define __HAL_CEC_GET_TRANSMISSION_START_FLAG(__HANDLE__) ((__HANDLE__)->Instance->CR & CEC_CR_TXSOM) + +/** @brief Get Transmission End flag + * @param __HANDLE__ specifies the CEC Handle. + * @retval FlagStatus + */ +#define __HAL_CEC_GET_TRANSMISSION_END_FLAG(__HANDLE__) ((__HANDLE__)->Instance->CR & CEC_CR_TXEOM) + +/** @brief Clear OAR register + * @param __HANDLE__ specifies the CEC Handle. + * @retval none + */ +#define __HAL_CEC_CLEAR_OAR(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CFGR, CEC_CFGR_OAR) + +/** @brief Set OAR register (without resetting previously set address in case of multi-address mode) + * To reset OAR, __HAL_CEC_CLEAR_OAR() needs to be called beforehand + * @param __HANDLE__ specifies the CEC Handle. + * @param __ADDRESS__ Own Address value (CEC logical address is identified by bit position) + * @retval none + */ +#define __HAL_CEC_SET_OAR(__HANDLE__,__ADDRESS__) SET_BIT((__HANDLE__)->Instance->CFGR, (__ADDRESS__)<< CEC_CFGR_OAR_LSB_POS) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup CEC_Exported_Functions + * @{ + */ + +/** @addtogroup CEC_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec); +HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec); +HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress); +void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec); +void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec); + +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID, + pCEC_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec); +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup CEC_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ***************************************************/ +HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress, + const uint8_t *pData, uint32_t Size); +uint32_t HAL_CEC_GetLastReceivedFrameSize(const CEC_HandleTypeDef *hcec); +void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer); +void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec); +void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec); +void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize); +void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec); +/** + * @} + */ + +/** @addtogroup CEC_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_CEC_StateTypeDef HAL_CEC_GetState(const CEC_HandleTypeDef *hcec); +uint32_t HAL_CEC_GetError(const CEC_HandleTypeDef *hcec); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup CEC_Private_Types CEC Private Types + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup CEC_Private_Variables CEC Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup CEC_Private_Constants CEC Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup CEC_Private_Macros CEC Private Macros + * @{ + */ + +#define IS_CEC_SIGNALFREETIME(__SFT__) ((__SFT__) <= CEC_CFGR_SFT) + +#define IS_CEC_TOLERANCE(__RXTOL__) (((__RXTOL__) == CEC_STANDARD_TOLERANCE) || \ + ((__RXTOL__) == CEC_EXTENDED_TOLERANCE)) + +#define IS_CEC_BRERXSTOP(__BRERXSTOP__) (((__BRERXSTOP__) == CEC_NO_RX_STOP_ON_BRE) || \ + ((__BRERXSTOP__) == CEC_RX_STOP_ON_BRE)) + +#define IS_CEC_BREERRORBITGEN(__ERRORBITGEN__) (((__ERRORBITGEN__) == CEC_BRE_ERRORBIT_NO_GENERATION) || \ + ((__ERRORBITGEN__) == CEC_BRE_ERRORBIT_GENERATION)) + +#define IS_CEC_LBPEERRORBITGEN(__ERRORBITGEN__) (((__ERRORBITGEN__) == CEC_LBPE_ERRORBIT_NO_GENERATION) || \ + ((__ERRORBITGEN__) == CEC_LBPE_ERRORBIT_GENERATION)) + +#define IS_CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION(__ERRORBITGEN__) (((__ERRORBITGEN__) == CEC_BROADCASTERROR_ERRORBIT_GENERATION) || \ + ((__ERRORBITGEN__) == CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION)) + +#define IS_CEC_SFTOP(__SFTOP__) (((__SFTOP__) == CEC_SFT_START_ON_TXSOM) || \ + ((__SFTOP__) == CEC_SFT_START_ON_TX_RX_END)) + +#define IS_CEC_LISTENING_MODE(__MODE__) (((__MODE__) == CEC_REDUCED_LISTENING_MODE) || \ + ((__MODE__) == CEC_FULL_LISTENING_MODE)) + +/** @brief Check CEC message size. + * The message size is the payload size: without counting the header, + * it varies from 0 byte (ping operation, one header only, no payload) to + * 15 bytes (1 opcode and up to 14 operands following the header). + * @param __SIZE__ CEC message size. + * @retval Test result (TRUE or FALSE). + */ +#define IS_CEC_MSGSIZE(__SIZE__) ((__SIZE__) <= 0x10U) + +/** @brief Check CEC device Own Address Register (OAR) setting. + * OAR address is written in a 15-bit field within CEC_CFGR register. + * @param __ADDRESS__ CEC own address. + * @retval Test result (TRUE or FALSE). + */ +#define IS_CEC_OWN_ADDRESS(__ADDRESS__) ((__ADDRESS__) <= 0x7FFFU) + +/** @brief Check CEC initiator or destination logical address setting. + * Initiator and destination addresses are coded over 4 bits. + * @param __ADDRESS__ CEC initiator or logical address. + * @retval Test result (TRUE or FALSE). + */ +#define IS_CEC_ADDRESS(__ADDRESS__) ((__ADDRESS__) <= 0xFU) +/** + * @} + */ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup CEC_Private_Functions CEC Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* CEC */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xxHAL_CEC_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf.h new file mode 100644 index 0000000..c0f701d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf.h @@ -0,0 +1,500 @@ +/** +****************************************************************************** +* @file stm32f4xx_hal_conf_template.h +* @author MCD Application Team +* @brief HAL configuration template file. +* This file should be copied to the application folder and renamed +* to stm32f4xx_hal_conf.h. +****************************************************************************** +* @attention +* +* Copyright (c) 2017 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 __STM32F4xx_HAL_CONF_H +#define __STM32F4xx_HAL_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** +* @brief This is the list of modules to be used in the HAL driver +*/ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED +/* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +#define HAL_CRC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED +#define HAL_DAC_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_DMA2D_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_PCCARD_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LTDC_MODULE_ENABLED +#define HAL_DSI_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_QSPI_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_FMPI2C_MODULE_ENABLED +#define HAL_FMPSMBUS_MODULE_ENABLED +#define HAL_SPDIFRX_MODULE_ENABLED +#define HAL_DFSDM_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** +* @brief Adjust the value of External High Speed oscillator (HSE) used in your application. +* This value is used by the RCC HAL module to compute the system frequency +* (when HSE is used as system clock source, directly or through the PLL). +*/ +#if !defined (HSE_VALUE) + #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** +* @brief Internal High Speed oscillator (HSI) value. +* This value is used by the RCC HAL module to compute the system frequency +* (when HSI is used as system clock source, directly or through the PLL). +*/ +#if !defined (HSI_VALUE) + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */ +#endif /* HSI_VALUE */ + +/** +* @brief Internal Low Speed oscillator (LSI) value. +*/ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** +* @brief External Low Speed oscillator (LSE) value. +*/ +#if !defined (LSE_VALUE) + #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** +* @brief External clock source for I2S peripheral +* This value is used by the I2S HAL module to compute the I2S clock source +* frequency, this source is inserted directly through I2S_CKIN pad. +*/ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** +* @brief This is the HAL system configuration section +*/ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 1U +#define INSTRUCTION_CACHE_ENABLE 1U +#define DATA_CACHE_ENABLE 1U + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_FMPI2C_REGISTER_CALLBACKS 0U /* FMPI2C register callback disabled */ +#define USE_HAL_FMPSMBUS_REGISTER_CALLBACKS 0U /* FMPSMBUS register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCCARD_REGISTER_CALLBACKS 0U /* PCCARD register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** +* @brief Uncomment the line below to expanse the "assert_param" macro in the +* HAL drivers code +*/ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE 1528U /* ETH Max buffer size for receive */ +#define ETH_TX_BUF_SIZE 1528U /* ETH Max buffer size for transmit */ +#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY 0x000000FFU +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY 0x00000FFFU + +#define PHY_READ_TO 0x0000FFFFU +#define PHY_WRITE_TO 0x0000FFFFU + + /* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + + /* Section 4: Extended PHY Registers */ + +#define PHY_SR ((uint16_t)0x0010) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x0011) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ + +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ + +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ + + /* ################## SPI peripheral configuration ########################## */ + + /* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 1U + + /* Includes ------------------------------------------------------------------*/ + /** +* @brief Include module's header file +*/ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f4xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f4xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f4xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f4xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f4xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f4xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f4xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + #include "stm32f4xx_hal_can_legacy.h" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f4xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f4xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f4xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f4xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f4xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f4xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f4xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f4xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f4xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + #include "stm32f4xx_hal_pccard.h" +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f4xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f4xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f4xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f4xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f4xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f4xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f4xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f4xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f4xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f4xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f4xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f4xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f4xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f4xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f4xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f4xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f4xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f4xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f4xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f4xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f4xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f4xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f4xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED + #include "stm32f4xx_hal_fmpi2c.h" +#endif /* HAL_FMPI2C_MODULE_ENABLED */ + +#ifdef HAL_FMPSMBUS_MODULE_ENABLED + #include "stm32f4xx_hal_fmpsmbus.h" +#endif /* HAL_FMPSMBUS_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f4xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f4xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f4xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f4xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT + /** +* @brief The assert_param macro is used for function's parameters check. +* @param expr If expr is false, it calls assert_failed function +* which reports the name of the source file and the source +* line number of the call that failed. +* If expr is true, it returns no value. +* @retval None +*/ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) + /* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CONF_H */ + + + diff --git a/libs/hal/stm32f4xx_hal_conf.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h similarity index 70% rename from libs/hal/stm32f4xx_hal_conf.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h index b6917ab..c0c4484 100644 --- a/libs/hal/stm32f4xx_hal_conf.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_conf_template.h @@ -1,9 +1,8 @@ -/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file stm32f4xx_hal_conf_template.h * @author MCD Application Team - * @brief HAL configuration template file. + * @brief HAL configuration template file. * This file should be copied to the application folder and renamed * to stm32f4xx_hal_conf.h. ****************************************************************************** @@ -17,8 +16,7 @@ * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** - */ -/* USER CODE END Header */ + */ /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __STM32F4xx_HAL_CONF_H @@ -33,111 +31,108 @@ /* ########################## Module Selection ############################## */ /** - * @brief This is the list of modules to be used in the HAL driver + * @brief This is the list of modules to be used in the HAL driver */ -#define HAL_MODULE_ENABLED - - /* #define HAL_CRYP_MODULE_ENABLED */ -/* #define HAL_ADC_MODULE_ENABLED */ -/* #define HAL_CAN_MODULE_ENABLED */ -/* #define HAL_CRC_MODULE_ENABLED */ +#define HAL_MODULE_ENABLED +#define HAL_ADC_MODULE_ENABLED +#define HAL_CAN_MODULE_ENABLED /* #define HAL_CAN_LEGACY_MODULE_ENABLED */ +#define HAL_CRC_MODULE_ENABLED +#define HAL_CEC_MODULE_ENABLED +#define HAL_CRYP_MODULE_ENABLED #define HAL_DAC_MODULE_ENABLED -/* #define HAL_DCMI_MODULE_ENABLED */ -/* #define HAL_DMA2D_MODULE_ENABLED */ -/* #define HAL_ETH_MODULE_ENABLED */ -/* #define HAL_ETH_LEGACY_MODULE_ENABLED */ -/* #define HAL_NAND_MODULE_ENABLED */ -/* #define HAL_NOR_MODULE_ENABLED */ -/* #define HAL_PCCARD_MODULE_ENABLED */ -/* #define HAL_SRAM_MODULE_ENABLED */ -/* #define HAL_SDRAM_MODULE_ENABLED */ -/* #define HAL_HASH_MODULE_ENABLED */ -/* #define HAL_I2C_MODULE_ENABLED */ -/* #define HAL_I2S_MODULE_ENABLED */ -/* #define HAL_IWDG_MODULE_ENABLED */ -/* #define HAL_LTDC_MODULE_ENABLED */ -#define HAL_RNG_MODULE_ENABLED -/* #define HAL_RTC_MODULE_ENABLED */ -/* #define HAL_SAI_MODULE_ENABLED */ -/* #define HAL_SD_MODULE_ENABLED */ -/* #define HAL_MMC_MODULE_ENABLED */ -/* #define HAL_SPI_MODULE_ENABLED */ -#define HAL_TIM_MODULE_ENABLED -/* #define HAL_UART_MODULE_ENABLED */ -/* #define HAL_USART_MODULE_ENABLED */ -/* #define HAL_IRDA_MODULE_ENABLED */ -/* #define HAL_SMARTCARD_MODULE_ENABLED */ -/* #define HAL_SMBUS_MODULE_ENABLED */ -/* #define HAL_WWDG_MODULE_ENABLED */ -#define HAL_PCD_MODULE_ENABLED -/* #define HAL_HCD_MODULE_ENABLED */ -/* #define HAL_DSI_MODULE_ENABLED */ -/* #define HAL_QSPI_MODULE_ENABLED */ -/* #define HAL_QSPI_MODULE_ENABLED */ -/* #define HAL_CEC_MODULE_ENABLED */ -/* #define HAL_FMPI2C_MODULE_ENABLED */ -/* #define HAL_FMPSMBUS_MODULE_ENABLED */ -/* #define HAL_SPDIFRX_MODULE_ENABLED */ -/* #define HAL_DFSDM_MODULE_ENABLED */ -/* #define HAL_LPTIM_MODULE_ENABLED */ -#define HAL_GPIO_MODULE_ENABLED -#define HAL_EXTI_MODULE_ENABLED +#define HAL_DCMI_MODULE_ENABLED #define HAL_DMA_MODULE_ENABLED -#define HAL_RCC_MODULE_ENABLED +#define HAL_DMA2D_MODULE_ENABLED +#define HAL_ETH_MODULE_ENABLED #define HAL_FLASH_MODULE_ENABLED +#define HAL_NAND_MODULE_ENABLED +#define HAL_NOR_MODULE_ENABLED +#define HAL_PCCARD_MODULE_ENABLED +#define HAL_SRAM_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED +#define HAL_HASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_SMBUS_MODULE_ENABLED +#define HAL_I2S_MODULE_ENABLED +#define HAL_IWDG_MODULE_ENABLED +#define HAL_LTDC_MODULE_ENABLED +#define HAL_DSI_MODULE_ENABLED #define HAL_PWR_MODULE_ENABLED +#define HAL_QSPI_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RNG_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SAI_MODULE_ENABLED +#define HAL_SD_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED +#define HAL_IRDA_MODULE_ENABLED +#define HAL_SMARTCARD_MODULE_ENABLED +#define HAL_WWDG_MODULE_ENABLED #define HAL_CORTEX_MODULE_ENABLED +#define HAL_PCD_MODULE_ENABLED +#define HAL_HCD_MODULE_ENABLED +#define HAL_FMPI2C_MODULE_ENABLED +#define HAL_FMPSMBUS_MODULE_ENABLED +#define HAL_SPDIFRX_MODULE_ENABLED +#define HAL_DFSDM_MODULE_ENABLED +#define HAL_LPTIM_MODULE_ENABLED +#define HAL_MMC_MODULE_ENABLED /* ########################## HSE/HSI Values adaptation ##################### */ /** * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. * This value is used by the RCC HAL module to compute the system frequency - * (when HSE is used as system clock source, directly or through the PLL). + * (when HSE is used as system clock source, directly or through the PLL). */ -#if !defined (HSE_VALUE) - #define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */ +#if !defined (HSE_VALUE) + #define HSE_VALUE 25000000U /*!< Value of the External oscillator in Hz */ #endif /* HSE_VALUE */ #if !defined (HSE_STARTUP_TIMEOUT) - #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ + #define HSE_STARTUP_TIMEOUT 100U /*!< Time out for HSE start up, in ms */ #endif /* HSE_STARTUP_TIMEOUT */ /** * @brief Internal High Speed oscillator (HSI) value. * This value is used by the RCC HAL module to compute the system frequency - * (when HSI is used as system clock source, directly or through the PLL). + * (when HSI is used as system clock source, directly or through the PLL). */ #if !defined (HSI_VALUE) - #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ + #define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */ #endif /* HSI_VALUE */ /** * @brief Internal Low Speed oscillator (LSI) value. */ -#if !defined (LSI_VALUE) - #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz*/ -#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz - The real value may vary depending on the variations - in voltage and temperature.*/ +#if !defined (LSI_VALUE) + #define LSI_VALUE 32000U /*!< LSI Typical Value in Hz */ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ /** * @brief External Low Speed oscillator (LSE) value. */ #if !defined (LSE_VALUE) - #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ + #define LSE_VALUE 32768U /*!< Value of the External Low Speed oscillator in Hz */ #endif /* LSE_VALUE */ #if !defined (LSE_STARTUP_TIMEOUT) - #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ + #define LSE_STARTUP_TIMEOUT 5000U /*!< Time out for LSE start up, in ms */ #endif /* LSE_STARTUP_TIMEOUT */ /** * @brief External clock source for I2S peripheral - * This value is used by the I2S HAL module to compute the I2S clock source - * frequency, this source is inserted directly through I2S_CKIN pad. + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. */ #if !defined (EXTERNAL_CLOCK_VALUE) - #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External audio frequency in Hz*/ + #define EXTERNAL_CLOCK_VALUE 12288000U /*!< Value of the External oscillator in Hz*/ #endif /* EXTERNAL_CLOCK_VALUE */ /* Tip: To avoid modifying this file each time you need to use different HSE, @@ -146,9 +141,9 @@ /* ########################### System Configuration ######################### */ /** * @brief This is the HAL system configuration section - */ -#define VDD_VALUE 3300U /*!< Value of VDD in mv */ -#define TICK_INT_PRIORITY 15U /*!< tick interrupt priority */ + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */ #define USE_RTOS 0U #define PREFETCH_ENABLE 1U #define INSTRUCTION_CACHE_ENABLE 1U @@ -196,10 +191,10 @@ /* ########################## Assert Selection ############################## */ /** - * @brief Uncomment the line below to expanse the "assert_param" macro in the + * @brief Uncomment the line below to expanse the "assert_param" macro in the * HAL drivers code */ -#define USE_FULL_ASSERT 1U +/* #define USE_FULL_ASSERT 1U */ /* ################## Ethernet peripheral configuration ##################### */ @@ -213,17 +208,17 @@ #define MAC_ADDR4 0U #define MAC_ADDR5 0U -/* Definition of the Ethernet driver buffers size and count */ -#define ETH_RX_BUF_SIZE /* buffer size for receive */ -#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ -#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ -#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE 1528U /* ETH Max buffer size for receive */ +#define ETH_TX_BUF_SIZE 1528U /* ETH Max buffer size for transmit */ +#define ETH_RXBUFNB 4U /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB 4U /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ /* Section 2: PHY configuration section */ -/* DP83848_PHY_ADDRESS Address*/ -#define DP83848_PHY_ADDRESS 0x01U -/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +/* DP83848 PHY Address*/ +#define DP83848_PHY_ADDRESS 0x01U +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ #define PHY_RESET_DELAY 0x000000FFU /* PHY Configuration delay */ #define PHY_CONFIG_DELAY 0x00000FFFU @@ -233,29 +228,39 @@ /* Section 3: Common PHY Registers */ -#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ -#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ +#define PHY_BCR ((uint16_t)0x0000) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ -#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ -#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ -#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ -#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ -#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ -#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ -#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ -#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ -#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ -#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ +#define PHY_SR ((uint16_t)0x0010) /*!< PHY status register Offset */ +#define PHY_MICR ((uint16_t)0x0011) /*!< MII Interrupt Control Register */ +#define PHY_MISR ((uint16_t)0x0012) /*!< MII Interrupt Status and Misc. Control Register */ + +#define PHY_LINK_STATUS ((uint16_t)0x0001) /*!< PHY Link mask */ +#define PHY_SPEED_STATUS ((uint16_t)0x0002) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)0x0004) /*!< PHY Duplex mask */ -#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ -#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ -#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ +#define PHY_MICR_INT_EN ((uint16_t)0x0002) /*!< PHY Enable interrupts */ +#define PHY_MICR_INT_OE ((uint16_t)0x0001) /*!< PHY Enable output interrupt events */ -/* Section 4: Extended PHY Registers */ -#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */ - -#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */ -#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */ +#define PHY_MISR_LINK_INT_EN ((uint16_t)0x0020) /*!< Enable Interrupt on change of link status */ +#define PHY_LINK_INTERRUPT ((uint16_t)0x2000) /*!< PHY link status interrupt mask */ /* ################## SPI peripheral configuration ########################## */ @@ -264,11 +269,11 @@ * Deactivated: CRC code cleaned from driver */ -#define USE_SPI_CRC 0U +#define USE_SPI_CRC 1U /* Includes ------------------------------------------------------------------*/ /** - * @brief Include module's header file + * @brief Include module's header file */ #ifdef HAL_RCC_MODULE_ENABLED @@ -286,7 +291,7 @@ #ifdef HAL_DMA_MODULE_ENABLED #include "stm32f4xx_hal_dma.h" #endif /* HAL_DMA_MODULE_ENABLED */ - + #ifdef HAL_CORTEX_MODULE_ENABLED #include "stm32f4xx_hal_cortex.h" #endif /* HAL_CORTEX_MODULE_ENABLED */ @@ -308,7 +313,7 @@ #endif /* HAL_CRC_MODULE_ENABLED */ #ifdef HAL_CRYP_MODULE_ENABLED - #include "stm32f4xx_hal_cryp.h" + #include "stm32f4xx_hal_cryp.h" #endif /* HAL_CRYP_MODULE_ENABLED */ #ifdef HAL_DMA2D_MODULE_ENABLED @@ -327,14 +332,10 @@ #include "stm32f4xx_hal_eth.h" #endif /* HAL_ETH_MODULE_ENABLED */ -#ifdef HAL_ETH_LEGACY_MODULE_ENABLED - #include "stm32f4xx_hal_eth_legacy.h" -#endif /* HAL_ETH_LEGACY_MODULE_ENABLED */ - #ifdef HAL_FLASH_MODULE_ENABLED #include "stm32f4xx_hal_flash.h" #endif /* HAL_FLASH_MODULE_ENABLED */ - + #ifdef HAL_SRAM_MODULE_ENABLED #include "stm32f4xx_hal_sram.h" #endif /* HAL_SRAM_MODULE_ENABLED */ @@ -349,8 +350,8 @@ #ifdef HAL_PCCARD_MODULE_ENABLED #include "stm32f4xx_hal_pccard.h" -#endif /* HAL_PCCARD_MODULE_ENABLED */ - +#endif /* HAL_PCCARD_MODULE_ENABLED */ + #ifdef HAL_SDRAM_MODULE_ENABLED #include "stm32f4xx_hal_sdram.h" #endif /* HAL_SDRAM_MODULE_ENABLED */ @@ -434,7 +435,7 @@ #ifdef HAL_HCD_MODULE_ENABLED #include "stm32f4xx_hal_hcd.h" #endif /* HAL_HCD_MODULE_ENABLED */ - + #ifdef HAL_DSI_MODULE_ENABLED #include "stm32f4xx_hal_dsi.h" #endif /* HAL_DSI_MODULE_ENABLED */ @@ -477,7 +478,7 @@ * @brief The assert_param macro is used for function's parameters check. * @param expr If expr is false, it calls assert_failed function * which reports the name of the source file and the source - * line number of the call that failed. + * line number of the call that failed. * If expr is true, it returns no value. * @retval None */ @@ -488,8 +489,12 @@ #define assert_param(expr) ((void)0U) #endif /* USE_FULL_ASSERT */ + #ifdef __cplusplus } #endif #endif /* __STM32F4xx_HAL_CONF_H */ + + + diff --git a/libs/hal/stm32f4xx_hal_cortex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_cortex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cortex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h new file mode 100644 index 0000000..41edbe3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_crc.h @@ -0,0 +1,181 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_crc.h + * @author MCD Application Team + * @brief Header file of CRC 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 STM32F4xx_HAL_CRC_H +#define STM32F4xx_HAL_CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CRC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CRC_Exported_Types CRC Exported Types + * @{ + */ + +/** + * @brief CRC HAL State Structure definition + */ +typedef enum +{ + HAL_CRC_STATE_RESET = 0x00U, /*!< CRC not yet initialized or disabled */ + HAL_CRC_STATE_READY = 0x01U, /*!< CRC initialized and ready for use */ + HAL_CRC_STATE_BUSY = 0x02U, /*!< CRC internal process is ongoing */ + HAL_CRC_STATE_TIMEOUT = 0x03U, /*!< CRC timeout state */ + HAL_CRC_STATE_ERROR = 0x04U /*!< CRC error state */ +} HAL_CRC_StateTypeDef; + + +/** + * @brief CRC Handle Structure definition + */ +typedef struct +{ + CRC_TypeDef *Instance; /*!< Register base address */ + + HAL_LockTypeDef Lock; /*!< CRC Locking object */ + + __IO HAL_CRC_StateTypeDef State; /*!< CRC communication state */ + +} CRC_HandleTypeDef; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CRC_Exported_Constants CRC Exported Constants + * @{ + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CRC_Exported_Macros CRC Exported Macros + * @{ + */ + +/** @brief Reset CRC handle state. + * @param __HANDLE__ CRC handle. + * @retval None + */ +#define __HAL_CRC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CRC_STATE_RESET) + +/** + * @brief Reset CRC Data Register. + * @param __HANDLE__ CRC handle + * @retval None + */ +#define __HAL_CRC_DR_RESET(__HANDLE__) ((__HANDLE__)->Instance->CR |= CRC_CR_RESET) + +/** + * @brief Store data in the Independent Data (ID) register. + * @param __HANDLE__ CRC handle + * @param __VALUE__ Value to be stored in the ID register + * @note Refer to the Reference Manual to get the authorized __VALUE__ length in bits + * @retval None + */ +#define __HAL_CRC_SET_IDR(__HANDLE__, __VALUE__) (WRITE_REG((__HANDLE__)->Instance->IDR, (__VALUE__))) + +/** + * @brief Return the data stored in the Independent Data (ID) register. + * @param __HANDLE__ CRC handle + * @note Refer to the Reference Manual to get the authorized __VALUE__ length in bits + * @retval Value of the ID register + */ +#define __HAL_CRC_GET_IDR(__HANDLE__) (((__HANDLE__)->Instance->IDR) & CRC_IDR_IDR) +/** + * @} + */ + + +/* Private macros --------------------------------------------------------*/ +/** @defgroup CRC_Private_Macros CRC Private Macros + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CRC_Exported_Functions CRC Exported Functions + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +/** @defgroup CRC_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc); +HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc); +void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc); +void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc); +/** + * @} + */ + +/* Peripheral Control functions ***********************************************/ +/** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions + * @{ + */ +uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength); +uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength); +/** + * @} + */ + +/* Peripheral State and Error functions ***************************************/ +/** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions + * @{ + */ +HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_CRC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h new file mode 100644 index 0000000..960e1c7 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp.h @@ -0,0 +1,683 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cryp.h + * @author MCD Application Team + * @brief Header file of CRYP 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 __STM32F4xx_HAL_CRYP_H +#define __STM32F4xx_HAL_CRYP_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (AES) || defined (CRYP) +/** @addtogroup CRYP + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup CRYP_Exported_Types CRYP Exported Types + * @{ + */ + +/** + * @brief CRYP Init Structure definition + */ + +typedef struct +{ + uint32_t DataType; /*!< 32-bit data, 16-bit data, 8-bit data or 1-bit string. + This parameter can be a value of @ref CRYP_Data_Type */ + uint32_t KeySize; /*!< Used only in AES mode : 128, 192 or 256 bit key length in CRYP1. + 128 or 256 bit key length in TinyAES This parameter can be a value of @ref CRYP_Key_Size */ + uint32_t *pKey; /*!< The key used for encryption/decryption */ + uint32_t *pInitVect; /*!< The initialization vector used also as initialization + counter in CTR mode */ + uint32_t Algorithm; /*!< DES/ TDES Algorithm ECB/CBC + AES Algorithm ECB/CBC/CTR/GCM or CCM + This parameter can be a value of @ref CRYP_Algorithm_Mode */ + uint32_t *Header; /*!< used only in AES GCM and CCM Algorithm for authentication, + GCM : also known as Additional Authentication Data + CCM : named B1 composed of the associated data length and Associated Data. */ + uint32_t HeaderSize; /*!< The size of header buffer in word */ + uint32_t *B0; /*!< B0 is first authentication block used only in AES CCM mode */ + uint32_t DataWidthUnit; /*!< Data With Unit, this parameter can be value of @ref CRYP_Data_Width_Unit*/ + uint32_t HeaderWidthUnit; /*!< Header Width Unit, this parameter can be value of @ref CRYP_Header_Width_Unit*/ + uint32_t KeyIVConfigSkip; /*!< CRYP peripheral Key and IV configuration skip, to config Key and Initialization + Vector only once and to skip configuration for consecutive processings. + This parameter can be a value of @ref CRYP_Configuration_Skip */ + +} CRYP_ConfigTypeDef; + + +/** + * @brief CRYP State Structure definition + */ + +typedef enum +{ + HAL_CRYP_STATE_RESET = 0x00U, /*!< CRYP not yet initialized or disabled */ + HAL_CRYP_STATE_READY = 0x01U, /*!< CRYP initialized and ready for use */ + HAL_CRYP_STATE_BUSY = 0x02U /*!< CRYP BUSY, internal processing is ongoing */ +} HAL_CRYP_STATETypeDef; + + +/** + * @brief CRYP handle Structure definition + */ + +typedef struct __CRYP_HandleTypeDef +{ +#if defined (CRYP) + CRYP_TypeDef *Instance; /*!< CRYP registers base address */ +#else /* AES*/ + AES_TypeDef *Instance; /*!< AES Register base address */ +#endif /* End AES or CRYP */ + + CRYP_ConfigTypeDef Init; /*!< CRYP required parameters */ + + FunctionalState AutoKeyDerivation; /*!< Used only in TinyAES to allows to bypass or not key write-up before decryption. + This parameter can be a value of ENABLE/DISABLE */ + + uint32_t *pCrypInBuffPtr; /*!< Pointer to CRYP processing (encryption, decryption,...) buffer */ + + uint32_t *pCrypOutBuffPtr; /*!< Pointer to CRYP processing (encryption, decryption,...) buffer */ + + __IO uint16_t CrypHeaderCount; /*!< Counter of header data */ + + __IO uint16_t CrypInCount; /*!< Counter of input data */ + + __IO uint16_t CrypOutCount; /*!< Counter of output data */ + + uint16_t Size; /*!< length of input data in word */ + + uint32_t Phase; /*!< CRYP peripheral phase */ + + DMA_HandleTypeDef *hdmain; /*!< CRYP In DMA handle parameters */ + + DMA_HandleTypeDef *hdmaout; /*!< CRYP Out DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< CRYP locking object */ + + __IO HAL_CRYP_STATETypeDef State; /*!< CRYP peripheral state */ + + __IO uint32_t ErrorCode; /*!< CRYP peripheral error code */ + + uint32_t KeyIVConfig; /*!< CRYP peripheral Key and IV configuration flag, used when + configuration can be skipped */ + + uint32_t SizesSum; /*!< Sum of successive payloads lengths (in bytes), stored + for a single signature computation after several + messages processing */ + +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + void (*InCpltCallback)(struct __CRYP_HandleTypeDef *hcryp); /*!< CRYP Input FIFO transfer completed callback */ + void (*OutCpltCallback)(struct __CRYP_HandleTypeDef *hcryp); /*!< CRYP Output FIFO transfer completed callback */ + void (*ErrorCallback)(struct __CRYP_HandleTypeDef *hcryp); /*!< CRYP Error callback */ + + void (* MspInitCallback)(struct __CRYP_HandleTypeDef *hcryp); /*!< CRYP Msp Init callback */ + void (* MspDeInitCallback)(struct __CRYP_HandleTypeDef *hcryp); /*!< CRYP Msp DeInit callback */ + +#endif /* (USE_HAL_CRYP_REGISTER_CALLBACKS) */ +} CRYP_HandleTypeDef; + + +/** + * @} + */ + +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) +/** @defgroup HAL_CRYP_Callback_ID_enumeration_definition HAL CRYP Callback ID enumeration definition + * @brief HAL CRYP Callback ID enumeration definition + * @{ + */ +typedef enum +{ + HAL_CRYP_INPUT_COMPLETE_CB_ID = 0x01U, /*!< CRYP Input FIFO transfer completed callback ID */ + HAL_CRYP_OUTPUT_COMPLETE_CB_ID = 0x02U, /*!< CRYP Output FIFO transfer completed callback ID */ + HAL_CRYP_ERROR_CB_ID = 0x03U, /*!< CRYP Error callback ID */ + + HAL_CRYP_MSPINIT_CB_ID = 0x04U, /*!< CRYP MspInit callback ID */ + HAL_CRYP_MSPDEINIT_CB_ID = 0x05U /*!< CRYP MspDeInit callback ID */ + +} HAL_CRYP_CallbackIDTypeDef; +/** + * @} + */ + +/** @defgroup HAL_CRYP_Callback_pointer_definition HAL CRYP Callback pointer definition + * @brief HAL CRYP Callback pointer definition + * @{ + */ + +typedef void (*pCRYP_CallbackTypeDef)(CRYP_HandleTypeDef *hcryp); /*!< pointer to a common CRYP callback function */ + +/** + * @} + */ + +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CRYP_Exported_Constants CRYP Exported Constants + * @{ + */ + +/** @defgroup CRYP_Error_Definition CRYP Error Definition + * @{ + */ +#define HAL_CRYP_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_CRYP_ERROR_WRITE 0x00000001U /*!< Write error */ +#define HAL_CRYP_ERROR_READ 0x00000002U /*!< Read error */ +#define HAL_CRYP_ERROR_DMA 0x00000004U /*!< DMA error */ +#define HAL_CRYP_ERROR_BUSY 0x00000008U /*!< Busy flag error */ +#define HAL_CRYP_ERROR_TIMEOUT 0x00000010U /*!< Timeout error */ +#define HAL_CRYP_ERROR_NOT_SUPPORTED 0x00000020U /*!< Not supported mode */ +#define HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE 0x00000040U /*!< Sequence are not respected only for GCM or CCM */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) +#define HAL_CRYP_ERROR_INVALID_CALLBACK ((uint32_t)0x00000080U) /*!< Invalid Callback error */ +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup CRYP_Data_Width_Unit CRYP Data Width Unit + * @{ + */ + +#define CRYP_DATAWIDTHUNIT_WORD 0x00000000U /*!< By default, size unit is word */ +#define CRYP_DATAWIDTHUNIT_BYTE 0x00000001U /*!< By default, size unit is word */ + +/** + * @} + */ + +/** @defgroup CRYP_Header_Width_Unit CRYP Header Width Unit + * @{ + */ + +#define CRYP_HEADERWIDTHUNIT_WORD 0x00000000U /*!< By default, header size unit is word */ +#define CRYP_HEADERWIDTHUNIT_BYTE 0x00000001U /*!< By default, header size unit is byte */ + +/** + * @} + */ + +/** @defgroup CRYP_Algorithm_Mode CRYP Algorithm Mode + * @{ + */ +#if defined(CRYP) + +#define CRYP_DES_ECB CRYP_CR_ALGOMODE_DES_ECB +#define CRYP_DES_CBC CRYP_CR_ALGOMODE_DES_CBC +#define CRYP_TDES_ECB CRYP_CR_ALGOMODE_TDES_ECB +#define CRYP_TDES_CBC CRYP_CR_ALGOMODE_TDES_CBC +#define CRYP_AES_ECB CRYP_CR_ALGOMODE_AES_ECB +#define CRYP_AES_CBC CRYP_CR_ALGOMODE_AES_CBC +#define CRYP_AES_CTR CRYP_CR_ALGOMODE_AES_CTR +#if defined (CRYP_CR_ALGOMODE_AES_GCM) +#define CRYP_AES_GCM CRYP_CR_ALGOMODE_AES_GCM +#define CRYP_AES_CCM CRYP_CR_ALGOMODE_AES_CCM +#endif /* GCM CCM defined*/ +#else /* AES*/ +#define CRYP_AES_ECB 0x00000000U /*!< Electronic codebook chaining algorithm */ +#define CRYP_AES_CBC AES_CR_CHMOD_0 /*!< Cipher block chaining algorithm */ +#define CRYP_AES_CTR AES_CR_CHMOD_1 /*!< Counter mode chaining algorithm */ +#define CRYP_AES_GCM_GMAC (AES_CR_CHMOD_0 | AES_CR_CHMOD_1) /*!< Galois counter mode - Galois message authentication code */ +#define CRYP_AES_CCM AES_CR_CHMOD_2 /*!< Counter with Cipher Mode */ +#endif /* End AES or CRYP */ + +/** + * @} + */ + +/** @defgroup CRYP_Key_Size CRYP Key Size + * @{ + */ +#if defined(CRYP) +#define CRYP_KEYSIZE_128B 0x00000000U +#define CRYP_KEYSIZE_192B CRYP_CR_KEYSIZE_0 +#define CRYP_KEYSIZE_256B CRYP_CR_KEYSIZE_1 +#else /* AES*/ +#define CRYP_KEYSIZE_128B 0x00000000U /*!< 128-bit long key */ +#define CRYP_KEYSIZE_256B AES_CR_KEYSIZE /*!< 256-bit long key */ +#endif /* End AES or CRYP */ +/** + * @} + */ + +/** @defgroup CRYP_Data_Type CRYP Data Type + * @{ + */ +#if defined(CRYP) +#define CRYP_DATATYPE_32B 0x00000000U +#define CRYP_DATATYPE_16B CRYP_CR_DATATYPE_0 +#define CRYP_DATATYPE_8B CRYP_CR_DATATYPE_1 +#define CRYP_DATATYPE_1B CRYP_CR_DATATYPE +#else /* AES*/ +#define CRYP_DATATYPE_32B 0x00000000U /*!< 32-bit data type (no swapping) */ +#define CRYP_DATATYPE_16B AES_CR_DATATYPE_0 /*!< 16-bit data type (half-word swapping) */ +#define CRYP_DATATYPE_8B AES_CR_DATATYPE_1 /*!< 8-bit data type (byte swapping) */ +#define CRYP_DATATYPE_1B AES_CR_DATATYPE /*!< 1-bit data type (bit swapping) */ +#endif /* End AES or CRYP */ + +/** + * @} + */ + +/** @defgroup CRYP_Interrupt CRYP Interrupt + * @{ + */ +#if defined (CRYP) +#define CRYP_IT_INI CRYP_IMSCR_INIM /*!< Input FIFO Interrupt */ +#define CRYP_IT_OUTI CRYP_IMSCR_OUTIM /*!< Output FIFO Interrupt */ +#else /* AES*/ +#define CRYP_IT_CCFIE AES_CR_CCFIE /*!< Computation Complete interrupt enable */ +#define CRYP_IT_ERRIE AES_CR_ERRIE /*!< Error interrupt enable */ +#define CRYP_IT_WRERR AES_SR_WRERR /*!< Write Error */ +#define CRYP_IT_RDERR AES_SR_RDERR /*!< Read Error */ +#define CRYP_IT_CCF AES_SR_CCF /*!< Computation completed */ +#endif /* End AES or CRYP */ + +/** + * @} + */ + +/** @defgroup CRYP_Flags CRYP Flags + * @{ + */ +#if defined (CRYP) +/* Flags in the SR register */ +#define CRYP_FLAG_IFEM CRYP_SR_IFEM /*!< Input FIFO is empty */ +#define CRYP_FLAG_IFNF CRYP_SR_IFNF /*!< Input FIFO is not Full */ +#define CRYP_FLAG_OFNE CRYP_SR_OFNE /*!< Output FIFO is not empty */ +#define CRYP_FLAG_OFFU CRYP_SR_OFFU /*!< Output FIFO is Full */ +#define CRYP_FLAG_BUSY CRYP_SR_BUSY /*!< The CRYP core is currently processing a block of data + or a key preparation (for AES decryption). */ +/* Flags in the RISR register */ +#define CRYP_FLAG_OUTRIS 0x01000002U /*!< Output FIFO service raw interrupt status */ +#define CRYP_FLAG_INRIS 0x01000001U /*!< Input FIFO service raw interrupt status*/ +#else /* AES*/ +/* status flags */ +#define CRYP_FLAG_BUSY AES_SR_BUSY /*!< GCM process suspension forbidden */ +#define CRYP_FLAG_WRERR AES_SR_WRERR /*!< Write Error */ +#define CRYP_FLAG_RDERR AES_SR_RDERR /*!< Read error */ +#define CRYP_FLAG_CCF AES_SR_CCF /*!< Computation completed */ +/* clearing flags */ +#define CRYP_CCF_CLEAR AES_CR_CCFC /*!< Computation Complete Flag Clear */ +#define CRYP_ERR_CLEAR AES_CR_ERRC /*!< Error Flag Clear */ +#endif /* End AES or CRYP */ + +/** + * @} + */ + +/** @defgroup CRYP_Configuration_Skip CRYP Key and IV Configuration Skip Mode + * @{ + */ + +#define CRYP_KEYIVCONFIG_ALWAYS 0x00000000U /*!< Peripheral Key and IV configuration to do systematically */ +#define CRYP_KEYIVCONFIG_ONCE 0x00000001U /*!< Peripheral Key and IV configuration to do only once */ + +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup CRYP_Exported_Macros CRYP Exported Macros + * @{ + */ + +/** @brief Reset CRYP handle state + * @param __HANDLE__ specifies the CRYP handle. + * @retval None + */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) +#define __HAL_CRYP_RESET_HANDLE_STATE(__HANDLE__) do{\ + (__HANDLE__)->State = HAL_CRYP_STATE_RESET;\ + (__HANDLE__)->MspInitCallback = NULL;\ + (__HANDLE__)->MspDeInitCallback = NULL;\ + }while(0) +#else +#define __HAL_CRYP_RESET_HANDLE_STATE(__HANDLE__) ( (__HANDLE__)->State = HAL_CRYP_STATE_RESET) +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + +/** + * @brief Enable/Disable the CRYP peripheral. + * @param __HANDLE__: specifies the CRYP handle. + * @retval None + */ +#if defined(CRYP) +#define __HAL_CRYP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= CRYP_CR_CRYPEN) +#define __HAL_CRYP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~CRYP_CR_CRYPEN) +#else /* AES*/ +#define __HAL_CRYP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= AES_CR_EN) +#define __HAL_CRYP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~AES_CR_EN) +#endif /* End AES or CRYP */ + +/** @brief Check whether the specified CRYP status flag is set or not. + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values for TinyAES: + * @arg @ref CRYP_FLAG_BUSY GCM process suspension forbidden + * @arg @ref CRYP_IT_WRERR Write Error + * @arg @ref CRYP_IT_RDERR Read Error + * @arg @ref CRYP_IT_CCF Computation Complete + * This parameter can be one of the following values for CRYP: + * @arg CRYP_FLAG_BUSY: The CRYP core is currently processing a block of data + * or a key preparation (for AES decryption). + * @arg CRYP_FLAG_IFEM: Input FIFO is empty + * @arg CRYP_FLAG_IFNF: Input FIFO is not full + * @arg CRYP_FLAG_INRIS: Input FIFO service raw interrupt is pending + * @arg CRYP_FLAG_OFNE: Output FIFO is not empty + * @arg CRYP_FLAG_OFFU: Output FIFO is full + * @arg CRYP_FLAG_OUTRIS: Input FIFO service raw interrupt is pending + * @retval The state of __FLAG__ (TRUE or FALSE). + */ +#define CRYP_FLAG_MASK 0x0000001FU +#if defined(CRYP) +#define __HAL_CRYP_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 24)) == 0x01U)?((((__HANDLE__)->Instance->RISR) & ((__FLAG__) & CRYP_FLAG_MASK)) == ((__FLAG__) & CRYP_FLAG_MASK)): \ + ((((__HANDLE__)->Instance->RISR) & ((__FLAG__) & CRYP_FLAG_MASK)) == ((__FLAG__) & CRYP_FLAG_MASK))) +#else /* AES*/ +#define __HAL_CRYP_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) +#endif /* End AES or CRYP */ + +/** @brief Clear the CRYP pending status flag. + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref CRYP_ERR_CLEAR Read (RDERR) or Write Error (WRERR) Flag Clear + * @arg @ref CRYP_CCF_CLEAR Computation Complete Flag (CCF) Clear + * @param __HANDLE__: specifies the CRYP handle. + * @retval None + */ + +#if defined(AES) +#define __HAL_CRYP_CLEAR_FLAG(__HANDLE__, __FLAG__) SET_BIT((__HANDLE__)->Instance->CR, (__FLAG__)) + + +/** @brief Check whether the specified CRYP interrupt source is enabled or not. + * @param __INTERRUPT__: CRYP interrupt source to check + * This parameter can be one of the following values for TinyAES: + * @arg @ref CRYP_IT_ERRIE Error interrupt (used for RDERR and WRERR) + * @arg @ref CRYP_IT_CCFIE Computation Complete interrupt + * @param __HANDLE__: specifies the CRYP handle. + * @retval State of interruption (TRUE or FALSE). + */ + +#define __HAL_CRYP_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR\ + & (__INTERRUPT__)) == (__INTERRUPT__)) + +#endif /* AES */ + +/** @brief Check whether the specified CRYP interrupt is set or not. + * @param __INTERRUPT__: specifies the interrupt to check. + * This parameter can be one of the following values for TinyAES: + * @arg @ref CRYP_IT_WRERR Write Error + * @arg @ref CRYP_IT_RDERR Read Error + * @arg @ref CRYP_IT_CCF Computation Complete + * This parameter can be one of the following values for CRYP: + * @arg CRYP_IT_INI: Input FIFO service masked interrupt status + * @arg CRYP_IT_OUTI: Output FIFO service masked interrupt status + * @param __HANDLE__: specifies the CRYP handle. + * @retval The state of __INTERRUPT__ (TRUE or FALSE). + */ +#if defined(CRYP) +#define __HAL_CRYP_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MISR\ + & (__INTERRUPT__)) == (__INTERRUPT__)) +#else /* AES*/ +#define __HAL_CRYP_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->SR & (__INTERRUPT__)) == (__INTERRUPT__)) +#endif /* End AES or CRYP */ + +/** + * @brief Enable the CRYP interrupt. + * @param __INTERRUPT__: CRYP Interrupt. + * This parameter can be one of the following values for TinyAES: + * @arg @ref CRYP_IT_ERRIE Error interrupt (used for RDERR and WRERR) + * @arg @ref CRYP_IT_CCFIE Computation Complete interrupt + * This parameter can be one of the following values for CRYP: + * @ CRYP_IT_INI : Input FIFO service interrupt mask. + * @ CRYP_IT_OUTI : Output FIFO service interrupt mask.CRYP interrupt. + * @param __HANDLE__: specifies the CRYP handle. + * @retval None + */ +#if defined(CRYP) +#define __HAL_CRYP_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IMSCR) |= (__INTERRUPT__)) +#else /* AES*/ +#define __HAL_CRYP_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR) |= (__INTERRUPT__)) +#endif /* End AES or CRYP */ + +/** + * @brief Disable the CRYP interrupt. + * @param __INTERRUPT__: CRYP Interrupt. + * This parameter can be one of the following values for TinyAES: + * @arg @ref CRYP_IT_ERRIE Error interrupt (used for RDERR and WRERR) + * @arg @ref CRYP_IT_CCFIE Computation Complete interrupt + * This parameter can be one of the following values for CRYP: + * @ CRYP_IT_INI : Input FIFO service interrupt mask. + * @ CRYP_IT_OUTI : Output FIFO service interrupt mask.CRYP interrupt. + * @param __HANDLE__: specifies the CRYP handle. + * @retval None + */ +#if defined(CRYP) +#define __HAL_CRYP_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IMSCR) &= ~(__INTERRUPT__)) +#else /* AES*/ +#define __HAL_CRYP_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CR) &= ~(__INTERRUPT__)) +#endif /* End AES or CRYP */ + +/** + * @} + */ +#if defined (CRYP_CR_ALGOMODE_AES_GCM)|| defined (AES) +/* Include CRYP HAL Extended module */ +#include "stm32f4xx_hal_cryp_ex.h" +#endif /* AES or GCM CCM defined*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CRYP_Exported_Functions CRYP Exported Functions + * @{ + */ + +/** @addtogroup CRYP_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_CRYP_Init(CRYP_HandleTypeDef *hcryp); +HAL_StatusTypeDef HAL_CRYP_DeInit(CRYP_HandleTypeDef *hcryp); +void HAL_CRYP_MspInit(CRYP_HandleTypeDef *hcryp); +void HAL_CRYP_MspDeInit(CRYP_HandleTypeDef *hcryp); +HAL_StatusTypeDef HAL_CRYP_SetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf); +HAL_StatusTypeDef HAL_CRYP_GetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_CRYP_RegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID, + pCRYP_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_CRYP_UnRegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup CRYP_Exported_Functions_Group2 + * @{ + */ + +/* encryption/decryption ***********************************/ +HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output, + uint32_t Timeout); +HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output, + uint32_t Timeout); +HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output); +HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output); +HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output); +HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output); + +/** + * @} + */ + + +/** @addtogroup CRYP_Exported_Functions_Group3 + * @{ + */ +/* Interrupt Handler functions **********************************************/ +void HAL_CRYP_IRQHandler(CRYP_HandleTypeDef *hcryp); +HAL_CRYP_STATETypeDef HAL_CRYP_GetState(CRYP_HandleTypeDef *hcryp); +void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp); +void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp); +void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp); +uint32_t HAL_CRYP_GetError(CRYP_HandleTypeDef *hcryp); + +/** + * @} + */ + +/** + * @} + */ + +/* Private macros --------------------------------------------------------*/ +/** @defgroup CRYP_Private_Macros CRYP Private Macros + * @{ + */ + +/** @defgroup CRYP_IS_CRYP_Definitions CRYP Private macros to check input parameters + * @{ + */ +#if defined(CRYP) +#if defined (CRYP_CR_ALGOMODE_AES_GCM) +#define IS_CRYP_ALGORITHM(ALGORITHM) (((ALGORITHM) == CRYP_DES_ECB) || \ + ((ALGORITHM) == CRYP_DES_CBC) || \ + ((ALGORITHM) == CRYP_TDES_ECB) || \ + ((ALGORITHM) == CRYP_TDES_CBC) || \ + ((ALGORITHM) == CRYP_AES_ECB) || \ + ((ALGORITHM) == CRYP_AES_CBC) || \ + ((ALGORITHM) == CRYP_AES_CTR) || \ + ((ALGORITHM) == CRYP_AES_GCM) || \ + ((ALGORITHM) == CRYP_AES_CCM)) +#else /*NO GCM CCM */ +#define IS_CRYP_ALGORITHM(ALGORITHM) (((ALGORITHM) == CRYP_DES_ECB) || \ + ((ALGORITHM) == CRYP_DES_CBC) || \ + ((ALGORITHM) == CRYP_TDES_ECB) || \ + ((ALGORITHM) == CRYP_TDES_CBC) || \ + ((ALGORITHM) == CRYP_AES_ECB) || \ + ((ALGORITHM) == CRYP_AES_CBC) || \ + ((ALGORITHM) == CRYP_AES_CTR)) +#endif /* GCM CCM defined*/ +#define IS_CRYP_KEYSIZE(KEYSIZE)(((KEYSIZE) == CRYP_KEYSIZE_128B) || \ + ((KEYSIZE) == CRYP_KEYSIZE_192B) || \ + ((KEYSIZE) == CRYP_KEYSIZE_256B)) +#else /* AES*/ +#define IS_CRYP_ALGORITHM(ALGORITHM) (((ALGORITHM) == CRYP_AES_ECB) || \ + ((ALGORITHM) == CRYP_AES_CBC) || \ + ((ALGORITHM) == CRYP_AES_CTR) || \ + ((ALGORITHM) == CRYP_AES_GCM_GMAC)|| \ + ((ALGORITHM) == CRYP_AES_CCM)) + + +#define IS_CRYP_KEYSIZE(KEYSIZE)(((KEYSIZE) == CRYP_KEYSIZE_128B) || \ + ((KEYSIZE) == CRYP_KEYSIZE_256B)) +#endif /* End AES or CRYP */ + +#define IS_CRYP_DATATYPE(DATATYPE)(((DATATYPE) == CRYP_DATATYPE_32B) || \ + ((DATATYPE) == CRYP_DATATYPE_16B) || \ + ((DATATYPE) == CRYP_DATATYPE_8B) || \ + ((DATATYPE) == CRYP_DATATYPE_1B)) + +#define IS_CRYP_INIT(CONFIG)(((CONFIG) == CRYP_KEYIVCONFIG_ALWAYS) || \ + ((CONFIG) == CRYP_KEYIVCONFIG_ONCE)) +/** + * @} + */ + +/** + * @} + */ + + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup CRYP_Private_Constants CRYP Private Constants + * @{ + */ + +/** + * @} + */ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup CRYP_Private_Defines CRYP Private Defines + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup CRYP_Private_Variables CRYP Private Variables + * @{ + */ + +/** + * @} + */ +/* Private functions prototypes ----------------------------------------------*/ +/** @defgroup CRYP_Private_Functions_Prototypes CRYP Private Functions Prototypes + * @{ + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup CRYP_Private_Functions CRYP Private Functions + * @{ + */ + +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ +#endif /* TinyAES or CRYP*/ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CRYP_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h new file mode 100644 index 0000000..dd12742 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_cryp_ex.h @@ -0,0 +1,142 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cryp_ex.h + * @author MCD Application Team + * @brief Header file of CRYP HAL Extension 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 __STM32F4xx_HAL_CRYP_EX_H +#define __STM32F4xx_HAL_CRYP_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup CRYPEx + * @{ + */ +/* Exported types ------------------------------------------------------------*/ +/** @defgroup CRYPEx_Exported_Types CRYPEx Exported types + * @{ + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CRYPEx_Exported_Constants CRYPEx Exported constants + * @{ + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup CRYPEx_Private_Types CRYPEx Private Types + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup CRYPEx_Private_Variables CRYPEx Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup CRYPEx_Private_Constants CRYPEx Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup CRYPEx_Private_Macros CRYPEx Private Macros + * @{ + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup CRYPEx_Private_Functions CRYPEx Private Functions + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CRYPEx_Exported_Functions CRYPEx Exported Functions + * @{ + */ +#if defined (CRYP) || defined (AES) +/** @addtogroup CRYPEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout); +HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout); +/** + * @} + */ +#endif /* CRYP||AES */ + +#if defined (AES) +/** @addtogroup CRYPEx_Exported_Functions_Group2 + * @{ + */ +void HAL_CRYPEx_EnableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp); +void HAL_CRYPEx_DisableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp); +/** + * @} + */ +#endif /* AES */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_CRYP_EX_H */ + diff --git a/libs/hal/stm32f4xx_hal_dac.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h similarity index 100% rename from libs/hal/stm32f4xx_hal_dac.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac.h diff --git a/libs/hal/stm32f4xx_hal_dac_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_dac_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dac_ex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h new file mode 100644 index 0000000..b7e82dc --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi.h @@ -0,0 +1,563 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dcmi.h + * @author MCD Application Team + * @brief Header file of DCMI HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_DCMI_H +#define __STM32F4xx_HAL_DCMI_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) ||\ + defined(STM32F479xx) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/* Include DCMI HAL Extended module */ +/* (include on top of file since DCMI structures are defined in extended file) */ +#include "stm32f4xx_hal_dcmi_ex.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DCMI DCMI + * @brief DCMI HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DCMI_Exported_Types DCMI Exported Types + * @{ + */ +/** + * @brief DCMI Embedded Synchronisation CODE Init structure definition + */ +typedef struct +{ + uint8_t FrameStartUnmask; /*!< Specifies the frame start delimiter unmask. */ + uint8_t LineStartUnmask; /*!< Specifies the line start delimiter unmask. */ + uint8_t LineEndUnmask; /*!< Specifies the line end delimiter unmask. */ + uint8_t FrameEndUnmask; /*!< Specifies the frame end delimiter unmask. */ +}DCMI_SyncUnmaskTypeDef; +/** + * @brief HAL DCMI State structures definition + */ +typedef enum +{ + HAL_DCMI_STATE_RESET = 0x00U, /*!< DCMI not yet initialized or disabled */ + HAL_DCMI_STATE_READY = 0x01U, /*!< DCMI initialized and ready for use */ + HAL_DCMI_STATE_BUSY = 0x02U, /*!< DCMI internal processing is ongoing */ + HAL_DCMI_STATE_TIMEOUT = 0x03U, /*!< DCMI timeout state */ + HAL_DCMI_STATE_ERROR = 0x04U, /*!< DCMI error state */ + HAL_DCMI_STATE_SUSPENDED = 0x05U /*!< DCMI suspend state */ +}HAL_DCMI_StateTypeDef; + +/** + * @brief DCMI handle Structure definition + */ +typedef struct __DCMI_HandleTypeDef +{ + DCMI_TypeDef *Instance; /*!< DCMI Register base address */ + + DCMI_InitTypeDef Init; /*!< DCMI parameters */ + + HAL_LockTypeDef Lock; /*!< DCMI locking object */ + + __IO HAL_DCMI_StateTypeDef State; /*!< DCMI state */ + + __IO uint32_t XferCount; /*!< DMA transfer counter */ + + __IO uint32_t XferSize; /*!< DMA transfer size */ + + uint32_t XferTransferNumber; /*!< DMA transfer number */ + + uint32_t pBuffPtr; /*!< Pointer to DMA output buffer */ + + DMA_HandleTypeDef *DMA_Handle; /*!< Pointer to the DMA handler */ + + __IO uint32_t ErrorCode; /*!< DCMI Error code */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + void (* FrameEventCallback) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Frame Event Callback */ + void (* VsyncEventCallback) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Vsync Event Callback */ + void (* LineEventCallback ) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Line Event Callback */ + void (* ErrorCallback) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Error Callback */ + void (* MspInitCallback) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Msp Init callback */ + void (* MspDeInitCallback) ( struct __DCMI_HandleTypeDef *hdcmi); /*!< DCMI Msp DeInit callback */ +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ +}DCMI_HandleTypeDef; + +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) +typedef enum +{ + HAL_DCMI_FRAME_EVENT_CB_ID = 0x00U, /*!< DCMI Frame Event Callback ID */ + HAL_DCMI_VSYNC_EVENT_CB_ID = 0x01U, /*!< DCMI Vsync Event Callback ID */ + HAL_DCMI_LINE_EVENT_CB_ID = 0x02U, /*!< DCMI Line Event Callback ID */ + HAL_DCMI_ERROR_CB_ID = 0x03U, /*!< DCMI Error Callback ID */ + HAL_DCMI_MSPINIT_CB_ID = 0x04U, /*!< DCMI MspInit callback ID */ + HAL_DCMI_MSPDEINIT_CB_ID = 0x05U /*!< DCMI MspDeInit callback ID */ + +}HAL_DCMI_CallbackIDTypeDef; + +typedef void (*pDCMI_CallbackTypeDef)(DCMI_HandleTypeDef *hdcmi); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DCMI_Exported_Constants DCMI Exported Constants + * @{ + */ + +/** @defgroup DCMI_Error_Code DCMI Error Code + * @{ + */ +#define HAL_DCMI_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_DCMI_ERROR_OVR 0x00000001U /*!< Overrun error */ +#define HAL_DCMI_ERROR_SYNC 0x00000002U /*!< Synchronization error */ +#define HAL_DCMI_ERROR_TIMEOUT 0x00000020U /*!< Timeout error */ +#define HAL_DCMI_ERROR_DMA 0x00000040U /*!< DMA error */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) +#define HAL_DCMI_ERROR_INVALID_CALLBACK ((uint32_t)0x00000080U) /*!< Invalid callback error */ +#endif +/** + * @} + */ + +/** @defgroup DCMI_Capture_Mode DCMI Capture Mode + * @{ + */ +#define DCMI_MODE_CONTINUOUS 0x00000000U /*!< The received data are transferred continuously + into the destination memory through the DMA */ +#define DCMI_MODE_SNAPSHOT ((uint32_t)DCMI_CR_CM) /*!< Once activated, the interface waits for the start of + frame and then transfers a single frame through the DMA */ +/** + * @} + */ + +/** @defgroup DCMI_Synchronization_Mode DCMI Synchronization Mode + * @{ + */ +#define DCMI_SYNCHRO_HARDWARE 0x00000000U /*!< Hardware synchronization data capture (frame/line start/stop) + is synchronized with the HSYNC/VSYNC signals */ +#define DCMI_SYNCHRO_EMBEDDED ((uint32_t)DCMI_CR_ESS) /*!< Embedded synchronization data capture is synchronized with + synchronization codes embedded in the data flow */ + +/** + * @} + */ + +/** @defgroup DCMI_PIXCK_Polarity DCMI PIXCK Polarity + * @{ + */ +#define DCMI_PCKPOLARITY_FALLING 0x00000000U /*!< Pixel clock active on Falling edge */ +#define DCMI_PCKPOLARITY_RISING ((uint32_t)DCMI_CR_PCKPOL) /*!< Pixel clock active on Rising edge */ + +/** + * @} + */ + +/** @defgroup DCMI_VSYNC_Polarity DCMI VSYNC Polarity + * @{ + */ +#define DCMI_VSPOLARITY_LOW 0x00000000U /*!< Vertical synchronization active Low */ +#define DCMI_VSPOLARITY_HIGH ((uint32_t)DCMI_CR_VSPOL) /*!< Vertical synchronization active High */ + +/** + * @} + */ + +/** @defgroup DCMI_HSYNC_Polarity DCMI HSYNC Polarity + * @{ + */ +#define DCMI_HSPOLARITY_LOW 0x00000000U /*!< Horizontal synchronization active Low */ +#define DCMI_HSPOLARITY_HIGH ((uint32_t)DCMI_CR_HSPOL) /*!< Horizontal synchronization active High */ + +/** + * @} + */ + +/** @defgroup DCMI_MODE_JPEG DCMI MODE JPEG + * @{ + */ +#define DCMI_JPEG_DISABLE 0x00000000U /*!< Mode JPEG Disabled */ +#define DCMI_JPEG_ENABLE ((uint32_t)DCMI_CR_JPEG) /*!< Mode JPEG Enabled */ + +/** + * @} + */ + +/** @defgroup DCMI_Capture_Rate DCMI Capture Rate + * @{ + */ +#define DCMI_CR_ALL_FRAME 0x00000000U /*!< All frames are captured */ +#define DCMI_CR_ALTERNATE_2_FRAME ((uint32_t)DCMI_CR_FCRC_0) /*!< Every alternate frame captured */ +#define DCMI_CR_ALTERNATE_4_FRAME ((uint32_t)DCMI_CR_FCRC_1) /*!< One frame in 4 frames captured */ + +/** + * @} + */ + +/** @defgroup DCMI_Extended_Data_Mode DCMI Extended Data Mode + * @{ + */ +#define DCMI_EXTEND_DATA_8B 0x00000000U /*!< Interface captures 8-bit data on every pixel clock */ +#define DCMI_EXTEND_DATA_10B ((uint32_t)DCMI_CR_EDM_0) /*!< Interface captures 10-bit data on every pixel clock */ +#define DCMI_EXTEND_DATA_12B ((uint32_t)DCMI_CR_EDM_1) /*!< Interface captures 12-bit data on every pixel clock */ +#define DCMI_EXTEND_DATA_14B ((uint32_t)(DCMI_CR_EDM_0 | DCMI_CR_EDM_1)) /*!< Interface captures 14-bit data on every pixel clock */ + +/** + * @} + */ + +/** @defgroup DCMI_Window_Coordinate DCMI Window Coordinate + * @{ + */ +#define DCMI_WINDOW_COORDINATE 0x3FFFU /*!< Window coordinate */ + +/** + * @} + */ + +/** @defgroup DCMI_Window_Height DCMI Window Height + * @{ + */ +#define DCMI_WINDOW_HEIGHT 0x1FFFU /*!< Window Height */ + +/** + * @} + */ + +/** @defgroup DCMI_Window_Vertical_Line DCMI Window Vertical Line + * @{ + */ +#define DCMI_POSITION_CWSIZE_VLINE (uint32_t)DCMI_CWSIZE_VLINE_Pos /*!< Required left shift to set crop window vertical line count */ +#define DCMI_POSITION_CWSTRT_VST (uint32_t)DCMI_CWSTRT_VST_Pos /*!< Required left shift to set crop window vertical start line count */ + +/** + * @} + */ + +/** @defgroup DCMI_interrupt_sources DCMI interrupt sources + * @{ + */ +#define DCMI_IT_FRAME ((uint32_t)DCMI_IER_FRAME_IE) /*!< Capture complete interrupt */ +#define DCMI_IT_OVR ((uint32_t)DCMI_IER_OVR_IE) /*!< Overrun interrupt */ +#define DCMI_IT_ERR ((uint32_t)DCMI_IER_ERR_IE) /*!< Synchronization error interrupt */ +#define DCMI_IT_VSYNC ((uint32_t)DCMI_IER_VSYNC_IE) /*!< VSYNC interrupt */ +#define DCMI_IT_LINE ((uint32_t)DCMI_IER_LINE_IE) /*!< Line interrupt */ +/** + * @} + */ + +/** @defgroup DCMI_Flags DCMI Flags + * @{ + */ + +/** + * @brief DCMI SR register + */ +#define DCMI_FLAG_HSYNC ((uint32_t)DCMI_SR_INDEX|DCMI_SR_HSYNC) /*!< HSYNC pin state (active line / synchronization between lines) */ +#define DCMI_FLAG_VSYNC ((uint32_t)DCMI_SR_INDEX|DCMI_SR_VSYNC) /*!< VSYNC pin state (active frame / synchronization between frames) */ +#define DCMI_FLAG_FNE ((uint32_t)DCMI_SR_INDEX|DCMI_SR_FNE) /*!< FIFO not empty flag */ +/** + * @brief DCMI RIS register + */ +#define DCMI_FLAG_FRAMERI ((uint32_t)DCMI_RISR_FRAME_RIS) /*!< Frame capture complete interrupt flag */ +#define DCMI_FLAG_OVRRI ((uint32_t)DCMI_RISR_OVR_RIS) /*!< Overrun interrupt flag */ +#define DCMI_FLAG_ERRRI ((uint32_t)DCMI_RISR_ERR_RIS) /*!< Synchronization error interrupt flag */ +#define DCMI_FLAG_VSYNCRI ((uint32_t)DCMI_RISR_VSYNC_RIS) /*!< VSYNC interrupt flag */ +#define DCMI_FLAG_LINERI ((uint32_t)DCMI_RISR_LINE_RIS) /*!< Line interrupt flag */ +/** + * @brief DCMI MIS register + */ +#define DCMI_FLAG_FRAMEMI ((uint32_t)DCMI_MIS_INDEX|DCMI_MIS_FRAME_MIS) /*!< DCMI Frame capture complete masked interrupt status */ +#define DCMI_FLAG_OVRMI ((uint32_t)DCMI_MIS_INDEX|DCMI_MIS_OVR_MIS ) /*!< DCMI Overrun masked interrupt status */ +#define DCMI_FLAG_ERRMI ((uint32_t)DCMI_MIS_INDEX|DCMI_MIS_ERR_MIS ) /*!< DCMI Synchronization error masked interrupt status */ +#define DCMI_FLAG_VSYNCMI ((uint32_t)DCMI_MIS_INDEX|DCMI_MIS_VSYNC_MIS) /*!< DCMI VSYNC masked interrupt status */ +#define DCMI_FLAG_LINEMI ((uint32_t)DCMI_MIS_INDEX|DCMI_MIS_LINE_MIS ) /*!< DCMI Line masked interrupt status */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup DCMI_Exported_Macros DCMI Exported Macros + * @{ + */ + +/** @brief Reset DCMI handle state + * @param __HANDLE__ specifies the DCMI handle. + * @retval None + */ +#define __HAL_DCMI_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_DCMI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) + +/** + * @brief Enable the DCMI. + * @param __HANDLE__ DCMI handle + * @retval None + */ +#define __HAL_DCMI_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= DCMI_CR_ENABLE) + +/** + * @brief Disable the DCMI. + * @param __HANDLE__ DCMI handle + * @retval None + */ +#define __HAL_DCMI_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(DCMI_CR_ENABLE)) + +/* Interrupt & Flag management */ +/** + * @brief Get the DCMI pending flag. + * @param __HANDLE__ DCMI handle + * @param __FLAG__ Get the specified flag. + * This parameter can be one of the following values (no combination allowed) + * @arg DCMI_FLAG_HSYNC: HSYNC pin state (active line / synchronization between lines) + * @arg DCMI_FLAG_VSYNC: VSYNC pin state (active frame / synchronization between frames) + * @arg DCMI_FLAG_FNE: FIFO empty flag + * @arg DCMI_FLAG_FRAMERI: Frame capture complete flag mask + * @arg DCMI_FLAG_OVRRI: Overrun flag mask + * @arg DCMI_FLAG_ERRRI: Synchronization error flag mask + * @arg DCMI_FLAG_VSYNCRI: VSYNC flag mask + * @arg DCMI_FLAG_LINERI: Line flag mask + * @arg DCMI_FLAG_FRAMEMI: DCMI Capture complete masked interrupt status + * @arg DCMI_FLAG_OVRMI: DCMI Overrun masked interrupt status + * @arg DCMI_FLAG_ERRMI: DCMI Synchronization error masked interrupt status + * @arg DCMI_FLAG_VSYNCMI: DCMI VSYNC masked interrupt status + * @arg DCMI_FLAG_LINEMI: DCMI Line masked interrupt status + * @retval The state of FLAG. + */ +#define __HAL_DCMI_GET_FLAG(__HANDLE__, __FLAG__)\ +((((__FLAG__) & (DCMI_SR_INDEX|DCMI_MIS_INDEX)) == 0x0U)? ((__HANDLE__)->Instance->RISR & (__FLAG__)) :\ + (((__FLAG__) & DCMI_SR_INDEX) == 0x0U)? ((__HANDLE__)->Instance->MISR & (__FLAG__)) : ((__HANDLE__)->Instance->SR & (__FLAG__))) + +/** + * @brief Clear the DCMI pending flags. + * @param __HANDLE__ DCMI handle + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DCMI_FLAG_FRAMERI: Frame capture complete flag mask + * @arg DCMI_FLAG_OVRRI: Overrun flag mask + * @arg DCMI_FLAG_ERRRI: Synchronization error flag mask + * @arg DCMI_FLAG_VSYNCRI: VSYNC flag mask + * @arg DCMI_FLAG_LINERI: Line flag mask + * @retval None + */ +#define __HAL_DCMI_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__)) + +/** + * @brief Enable the specified DCMI interrupts. + * @param __HANDLE__ DCMI handle + * @param __INTERRUPT__ specifies the DCMI interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg DCMI_IT_FRAME: Frame capture complete interrupt mask + * @arg DCMI_IT_OVR: Overrun interrupt mask + * @arg DCMI_IT_ERR: Synchronization error interrupt mask + * @arg DCMI_IT_VSYNC: VSYNC interrupt mask + * @arg DCMI_IT_LINE: Line interrupt mask + * @retval None + */ +#define __HAL_DCMI_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER |= (__INTERRUPT__)) + +/** + * @brief Disable the specified DCMI interrupts. + * @param __HANDLE__ DCMI handle + * @param __INTERRUPT__ specifies the DCMI interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg DCMI_IT_FRAME: Frame capture complete interrupt mask + * @arg DCMI_IT_OVR: Overrun interrupt mask + * @arg DCMI_IT_ERR: Synchronization error interrupt mask + * @arg DCMI_IT_VSYNC: VSYNC interrupt mask + * @arg DCMI_IT_LINE: Line interrupt mask + * @retval None + */ +#define __HAL_DCMI_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified DCMI interrupt has occurred or not. + * @param __HANDLE__ DCMI handle + * @param __INTERRUPT__ specifies the DCMI interrupt source to check. + * This parameter can be one of the following values: + * @arg DCMI_IT_FRAME: Frame capture complete interrupt mask + * @arg DCMI_IT_OVR: Overrun interrupt mask + * @arg DCMI_IT_ERR: Synchronization error interrupt mask + * @arg DCMI_IT_VSYNC: VSYNC interrupt mask + * @arg DCMI_IT_LINE: Line interrupt mask + * @retval The state of INTERRUPT. + */ +#define __HAL_DCMI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MISR & (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DCMI_Exported_Functions DCMI Exported Functions + * @{ + */ + +/** @addtogroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions + * @{ + */ +/* Initialization and de-initialization functions *****************************/ +HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi); +HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi); +void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup DCMI_Exported_Functions_Group2 IO operation functions + * @{ + */ +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length); +HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi); +HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef* hdcmi); +HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef* hdcmi); +void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_VsyncCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_HsyncCallback(DCMI_HandleTypeDef *hdcmi); +void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi); +/** + * @} + */ + +/** @addtogroup DCMI_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +/* Peripheral Control functions ***********************************************/ +HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize); +HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi); +HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi); +HAL_StatusTypeDef HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask); +/** + * @} + */ + +/** @addtogroup DCMI_Exported_Functions_Group4 Peripheral State functions + * @{ + */ +/* Peripheral State functions *************************************************/ +HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi); +uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup DCMI_Private_Constants DCMI Private Constants + * @{ + */ +#define DCMI_MIS_INDEX 0x1000U /*!< DCMI MIS register index */ +#define DCMI_SR_INDEX 0x2000U /*!< DCMI SR register index */ +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/** @defgroup DCMI_Private_Macros DCMI Private Macros + * @{ + */ +#define IS_DCMI_CAPTURE_MODE(MODE)(((MODE) == DCMI_MODE_CONTINUOUS) || \ + ((MODE) == DCMI_MODE_SNAPSHOT)) + +#define IS_DCMI_SYNCHRO(MODE)(((MODE) == DCMI_SYNCHRO_HARDWARE) || \ + ((MODE) == DCMI_SYNCHRO_EMBEDDED)) + +#define IS_DCMI_PCKPOLARITY(POLARITY)(((POLARITY) == DCMI_PCKPOLARITY_FALLING) || \ + ((POLARITY) == DCMI_PCKPOLARITY_RISING)) + +#define IS_DCMI_VSPOLARITY(POLARITY)(((POLARITY) == DCMI_VSPOLARITY_LOW) || \ + ((POLARITY) == DCMI_VSPOLARITY_HIGH)) + +#define IS_DCMI_HSPOLARITY(POLARITY)(((POLARITY) == DCMI_HSPOLARITY_LOW) || \ + ((POLARITY) == DCMI_HSPOLARITY_HIGH)) + +#define IS_DCMI_MODE_JPEG(JPEG_MODE)(((JPEG_MODE) == DCMI_JPEG_DISABLE) || \ + ((JPEG_MODE) == DCMI_JPEG_ENABLE)) + +#define IS_DCMI_CAPTURE_RATE(RATE) (((RATE) == DCMI_CR_ALL_FRAME) || \ + ((RATE) == DCMI_CR_ALTERNATE_2_FRAME) || \ + ((RATE) == DCMI_CR_ALTERNATE_4_FRAME)) + +#define IS_DCMI_EXTENDED_DATA(DATA)(((DATA) == DCMI_EXTEND_DATA_8B) || \ + ((DATA) == DCMI_EXTEND_DATA_10B) || \ + ((DATA) == DCMI_EXTEND_DATA_12B) || \ + ((DATA) == DCMI_EXTEND_DATA_14B)) + +#define IS_DCMI_WINDOW_COORDINATE(COORDINATE) ((COORDINATE) <= DCMI_WINDOW_COORDINATE) + +#define IS_DCMI_WINDOW_HEIGHT(HEIGHT) ((HEIGHT) <= DCMI_WINDOW_HEIGHT) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup DCMI_Private_Functions DCMI Private Functions + * @{ + */ + +/** + * @} + */ + +#endif /* STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_DCMI_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h new file mode 100644 index 0000000..b4f181c --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dcmi_ex.h @@ -0,0 +1,208 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dcmi_ex.h + * @author MCD Application Team + * @brief Header file of DCMI Extension HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_DCMI_EX_H +#define __STM32F4xx_HAL_DCMI_EX_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) ||\ + defined(STM32F479xx) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DCMIEx + * @brief DCMI HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DCMIEx_Exported_Types DCMI Extended Exported Types + * @{ + */ +/** + * @brief DCMIEx Embedded Synchronisation CODE Init structure definition + */ +typedef struct +{ + uint8_t FrameStartCode; /*!< Specifies the code of the frame start delimiter. */ + uint8_t LineStartCode; /*!< Specifies the code of the line start delimiter. */ + uint8_t LineEndCode; /*!< Specifies the code of the line end delimiter. */ + uint8_t FrameEndCode; /*!< Specifies the code of the frame end delimiter. */ +}DCMI_CodesInitTypeDef; + +/** + * @brief DCMI Init structure definition + */ +typedef struct +{ + uint32_t SynchroMode; /*!< Specifies the Synchronization Mode: Hardware or Embedded. + This parameter can be a value of @ref DCMI_Synchronization_Mode */ + + uint32_t PCKPolarity; /*!< Specifies the Pixel clock polarity: Falling or Rising. + This parameter can be a value of @ref DCMI_PIXCK_Polarity */ + + uint32_t VSPolarity; /*!< Specifies the Vertical synchronization polarity: High or Low. + This parameter can be a value of @ref DCMI_VSYNC_Polarity */ + + uint32_t HSPolarity; /*!< Specifies the Horizontal synchronization polarity: High or Low. + This parameter can be a value of @ref DCMI_HSYNC_Polarity */ + + uint32_t CaptureRate; /*!< Specifies the frequency of frame capture: All, 1/2 or 1/4. + This parameter can be a value of @ref DCMI_Capture_Rate */ + + uint32_t ExtendedDataMode; /*!< Specifies the data width: 8-bit, 10-bit, 12-bit or 14-bit. + This parameter can be a value of @ref DCMI_Extended_Data_Mode */ + + DCMI_CodesInitTypeDef SyncroCode; /*!< Specifies the code of the frame start delimiter. */ + + uint32_t JPEGMode; /*!< Enable or Disable the JPEG mode + This parameter can be a value of @ref DCMI_MODE_JPEG */ +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) + uint32_t ByteSelectMode; /*!< Specifies the data to be captured by the interface + This parameter can be a value of @ref DCMIEx_Byte_Select_Mode */ + + uint32_t ByteSelectStart; /*!< Specifies if the data to be captured by the interface is even or odd + This parameter can be a value of @ref DCMIEx_Byte_Select_Start */ + + uint32_t LineSelectMode; /*!< Specifies the line of data to be captured by the interface + This parameter can be a value of @ref DCMIEx_Line_Select_Mode */ + + uint32_t LineSelectStart; /*!< Specifies if the line of data to be captured by the interface is even or odd + This parameter can be a value of @ref DCMIEx_Line_Select_Start */ + +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ +}DCMI_InitTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/** @defgroup DCMIEx_Exported_Constants DCMI Exported Constants + * @{ + */ + +/** @defgroup DCMIEx_Byte_Select_Mode DCMI Byte Select Mode + * @{ + */ +#define DCMI_BSM_ALL 0x00000000U /*!< Interface captures all received data */ +#define DCMI_BSM_OTHER ((uint32_t)DCMI_CR_BSM_0) /*!< Interface captures every other byte from the received data */ +#define DCMI_BSM_ALTERNATE_4 ((uint32_t)DCMI_CR_BSM_1) /*!< Interface captures one byte out of four */ +#define DCMI_BSM_ALTERNATE_2 ((uint32_t)(DCMI_CR_BSM_0 | DCMI_CR_BSM_1)) /*!< Interface captures two bytes out of four */ + +/** + * @} + */ + +/** @defgroup DCMIEx_Byte_Select_Start DCMI Byte Select Start + * @{ + */ +#define DCMI_OEBS_ODD 0x00000000U /*!< Interface captures first data from the frame/line start, second one being dropped */ +#define DCMI_OEBS_EVEN ((uint32_t)DCMI_CR_OEBS) /*!< Interface captures second data from the frame/line start, first one being dropped */ + +/** + * @} + */ + +/** @defgroup DCMIEx_Line_Select_Mode DCMI Line Select Mode + * @{ + */ +#define DCMI_LSM_ALL 0x00000000U /*!< Interface captures all received lines */ +#define DCMI_LSM_ALTERNATE_2 ((uint32_t)DCMI_CR_LSM) /*!< Interface captures one line out of two */ + +/** + * @} + */ + +/** @defgroup DCMIEx_Line_Select_Start DCMI Line Select Start + * @{ + */ +#define DCMI_OELS_ODD 0x00000000U /*!< Interface captures first line from the frame start, second one being dropped */ +#define DCMI_OELS_EVEN ((uint32_t)DCMI_CR_OELS) /*!< Interface captures second line from the frame start, first one being dropped */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +#define DCMI_POSITION_ESCR_LSC (uint32_t)DCMI_ESCR_LSC_Pos /*!< Required left shift to set line start delimiter */ +#define DCMI_POSITION_ESCR_LEC (uint32_t)DCMI_ESCR_LEC_Pos /*!< Required left shift to set line end delimiter */ +#define DCMI_POSITION_ESCR_FEC (uint32_t)DCMI_ESCR_FEC_Pos /*!< Required left shift to set frame end delimiter */ + +/* Private macro -------------------------------------------------------------*/ +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/** @defgroup DCMIEx_Private_Macros DCMI Extended Private Macros + * @{ + */ +#define IS_DCMI_BYTE_SELECT_MODE(MODE)(((MODE) == DCMI_BSM_ALL) || \ + ((MODE) == DCMI_BSM_OTHER) || \ + ((MODE) == DCMI_BSM_ALTERNATE_4) || \ + ((MODE) == DCMI_BSM_ALTERNATE_2)) + +#define IS_DCMI_BYTE_SELECT_START(POLARITY)(((POLARITY) == DCMI_OEBS_ODD) || \ + ((POLARITY) == DCMI_OEBS_EVEN)) + +#define IS_DCMI_LINE_SELECT_MODE(MODE)(((MODE) == DCMI_LSM_ALL) || \ + ((MODE) == DCMI_LSM_ALTERNATE_2)) + +#define IS_DCMI_LINE_SELECT_START(POLARITY)(((POLARITY) == DCMI_OELS_ODD) || \ + ((POLARITY) == DCMI_OELS_EVEN)) +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +#endif /* STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ + + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_DCMI_H */ diff --git a/libs/hal/stm32f4xx_hal_def.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h similarity index 99% rename from libs/hal/stm32f4xx_hal_def.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h index f9bbec2..1df0d7d 100644 --- a/libs/hal/stm32f4xx_hal_def.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_def.h @@ -54,7 +54,9 @@ typedef enum /* Exported macro ------------------------------------------------------------*/ +#if !defined(UNUSED) #define UNUSED(X) (void)X /* To avoid gcc/g++ warnings */ +#endif /* UNUSED */ #define HAL_MAX_DELAY 0xFFFFFFFFU diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h new file mode 100644 index 0000000..2b0f193 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dfsdm.h @@ -0,0 +1,1141 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dfsdm.h + * @author MCD Application Team + * @brief Header file of DFSDM HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_DFSDM_H +#define __STM32F4xx_HAL_DFSDM_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup DFSDM + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DFSDM_Exported_Types DFSDM Exported Types + * @{ + */ + +/** + * @brief HAL DFSDM Channel states definition + */ +typedef enum +{ + HAL_DFSDM_CHANNEL_STATE_RESET = 0x00U, /*!< DFSDM channel not initialized */ + HAL_DFSDM_CHANNEL_STATE_READY = 0x01U, /*!< DFSDM channel initialized and ready for use */ + HAL_DFSDM_CHANNEL_STATE_ERROR = 0xFFU /*!< DFSDM channel state error */ +}HAL_DFSDM_Channel_StateTypeDef; + +/** + * @brief DFSDM channel output clock structure definition + */ +typedef struct +{ + FunctionalState Activation; /*!< Output clock enable/disable */ + uint32_t Selection; /*!< Output clock is system clock or audio clock. + This parameter can be a value of @ref DFSDM_Channel_OutputClock */ + uint32_t Divider; /*!< Output clock divider. + This parameter must be a number between Min_Data = 2 and Max_Data = 256 */ +}DFSDM_Channel_OutputClockTypeDef; + +/** + * @brief DFSDM channel input structure definition + */ +typedef struct +{ + uint32_t Multiplexer; /*!< Input is external serial inputs or internal register. + This parameter can be a value of @ref DFSDM_Channel_InputMultiplexer */ + uint32_t DataPacking; /*!< Standard, interleaved or dual mode for internal register. + This parameter can be a value of @ref DFSDM_Channel_DataPacking */ + uint32_t Pins; /*!< Input pins are taken from same or following channel. + This parameter can be a value of @ref DFSDM_Channel_InputPins */ +}DFSDM_Channel_InputTypeDef; + +/** + * @brief DFSDM channel serial interface structure definition + */ +typedef struct +{ + uint32_t Type; /*!< SPI or Manchester modes. + This parameter can be a value of @ref DFSDM_Channel_SerialInterfaceType */ + uint32_t SpiClock; /*!< SPI clock select (external or internal with different sampling point). + This parameter can be a value of @ref DFSDM_Channel_SpiClock */ +}DFSDM_Channel_SerialInterfaceTypeDef; + +/** + * @brief DFSDM channel analog watchdog structure definition + */ +typedef struct +{ + uint32_t FilterOrder; /*!< Analog watchdog Sinc filter order. + This parameter can be a value of @ref DFSDM_Channel_AwdFilterOrder */ + uint32_t Oversampling; /*!< Analog watchdog filter oversampling ratio. + This parameter must be a number between Min_Data = 1 and Max_Data = 32 */ +}DFSDM_Channel_AwdTypeDef; + +/** + * @brief DFSDM channel init structure definition + */ +typedef struct +{ + DFSDM_Channel_OutputClockTypeDef OutputClock; /*!< DFSDM channel output clock parameters */ + DFSDM_Channel_InputTypeDef Input; /*!< DFSDM channel input parameters */ + DFSDM_Channel_SerialInterfaceTypeDef SerialInterface; /*!< DFSDM channel serial interface parameters */ + DFSDM_Channel_AwdTypeDef Awd; /*!< DFSDM channel analog watchdog parameters */ + int32_t Offset; /*!< DFSDM channel offset. + This parameter must be a number between Min_Data = -8388608 and Max_Data = 8388607 */ + uint32_t RightBitShift; /*!< DFSDM channel right bit shift. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x1F */ +}DFSDM_Channel_InitTypeDef; + +/** + * @brief DFSDM channel handle structure definition + */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +typedef struct __DFSDM_Channel_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */ +{ + DFSDM_Channel_TypeDef *Instance; /*!< DFSDM channel instance */ + DFSDM_Channel_InitTypeDef Init; /*!< DFSDM channel init parameters */ + HAL_DFSDM_Channel_StateTypeDef State; /*!< DFSDM channel state */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + void (*CkabCallback) (struct __DFSDM_Channel_HandleTypeDef *hdfsdm_channel); /*!< DFSDM channel clock absence detection callback */ + void (*ScdCallback) (struct __DFSDM_Channel_HandleTypeDef *hdfsdm_channel); /*!< DFSDM channel short circuit detection callback */ + void (*MspInitCallback) (struct __DFSDM_Channel_HandleTypeDef *hdfsdm_channel); /*!< DFSDM channel MSP init callback */ + void (*MspDeInitCallback) (struct __DFSDM_Channel_HandleTypeDef *hdfsdm_channel); /*!< DFSDM channel MSP de-init callback */ +#endif +}DFSDM_Channel_HandleTypeDef; + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/** + * @brief DFSDM channel callback ID enumeration definition + */ +typedef enum +{ + HAL_DFSDM_CHANNEL_CKAB_CB_ID = 0x00U, /*!< DFSDM channel clock absence detection callback ID */ + HAL_DFSDM_CHANNEL_SCD_CB_ID = 0x01U, /*!< DFSDM channel short circuit detection callback ID */ + HAL_DFSDM_CHANNEL_MSPINIT_CB_ID = 0x02U, /*!< DFSDM channel MSP init callback ID */ + HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID = 0x03U /*!< DFSDM channel MSP de-init callback ID */ +}HAL_DFSDM_Channel_CallbackIDTypeDef; + +/** + * @brief DFSDM channel callback pointer definition + */ +typedef void (*pDFSDM_Channel_CallbackTypeDef)(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +#endif +/** + * @brief HAL DFSDM Filter states definition + */ +typedef enum +{ + HAL_DFSDM_FILTER_STATE_RESET = 0x00U, /*!< DFSDM filter not initialized */ + HAL_DFSDM_FILTER_STATE_READY = 0x01U, /*!< DFSDM filter initialized and ready for use */ + HAL_DFSDM_FILTER_STATE_REG = 0x02U, /*!< DFSDM filter regular conversion in progress */ + HAL_DFSDM_FILTER_STATE_INJ = 0x03U, /*!< DFSDM filter injected conversion in progress */ + HAL_DFSDM_FILTER_STATE_REG_INJ = 0x04U, /*!< DFSDM filter regular and injected conversions in progress */ + HAL_DFSDM_FILTER_STATE_ERROR = 0xFFU /*!< DFSDM filter state error */ +}HAL_DFSDM_Filter_StateTypeDef; + +/** + * @brief DFSDM filter regular conversion parameters structure definition + */ +typedef struct +{ + uint32_t Trigger; /*!< Trigger used to start regular conversion: software or synchronous. + This parameter can be a value of @ref DFSDM_Filter_Trigger */ + FunctionalState FastMode; /*!< Enable/disable fast mode for regular conversion */ + FunctionalState DmaMode; /*!< Enable/disable DMA for regular conversion */ +}DFSDM_Filter_RegularParamTypeDef; + +/** + * @brief DFSDM filter injected conversion parameters structure definition + */ +typedef struct +{ + uint32_t Trigger; /*!< Trigger used to start injected conversion: software, external or synchronous. + This parameter can be a value of @ref DFSDM_Filter_Trigger */ + FunctionalState ScanMode; /*!< Enable/disable scanning mode for injected conversion */ + FunctionalState DmaMode; /*!< Enable/disable DMA for injected conversion */ + uint32_t ExtTrigger; /*!< External trigger. + This parameter can be a value of @ref DFSDM_Filter_ExtTrigger */ + uint32_t ExtTriggerEdge; /*!< External trigger edge: rising, falling or both. + This parameter can be a value of @ref DFSDM_Filter_ExtTriggerEdge */ +}DFSDM_Filter_InjectedParamTypeDef; + +/** + * @brief DFSDM filter parameters structure definition + */ +typedef struct +{ + uint32_t SincOrder; /*!< Sinc filter order. + This parameter can be a value of @ref DFSDM_Filter_SincOrder */ + uint32_t Oversampling; /*!< Filter oversampling ratio. + This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */ + uint32_t IntOversampling; /*!< Integrator oversampling ratio. + This parameter must be a number between Min_Data = 1 and Max_Data = 256 */ +}DFSDM_Filter_FilterParamTypeDef; + +/** + * @brief DFSDM filter init structure definition + */ +typedef struct +{ + DFSDM_Filter_RegularParamTypeDef RegularParam; /*!< DFSDM regular conversion parameters */ + DFSDM_Filter_InjectedParamTypeDef InjectedParam; /*!< DFSDM injected conversion parameters */ + DFSDM_Filter_FilterParamTypeDef FilterParam; /*!< DFSDM filter parameters */ +}DFSDM_Filter_InitTypeDef; + +/** + * @brief DFSDM filter handle structure definition + */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +typedef struct __DFSDM_Filter_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */ +{ + DFSDM_Filter_TypeDef *Instance; /*!< DFSDM filter instance */ + DFSDM_Filter_InitTypeDef Init; /*!< DFSDM filter init parameters */ + DMA_HandleTypeDef *hdmaReg; /*!< Pointer on DMA handler for regular conversions */ + DMA_HandleTypeDef *hdmaInj; /*!< Pointer on DMA handler for injected conversions */ + uint32_t RegularContMode; /*!< Regular conversion continuous mode */ + uint32_t RegularTrigger; /*!< Trigger used for regular conversion */ + uint32_t InjectedTrigger; /*!< Trigger used for injected conversion */ + uint32_t ExtTriggerEdge; /*!< Rising, falling or both edges selected */ + FunctionalState InjectedScanMode; /*!< Injected scanning mode */ + uint32_t InjectedChannelsNbr; /*!< Number of channels in injected sequence */ + uint32_t InjConvRemaining; /*!< Injected conversions remaining */ + HAL_DFSDM_Filter_StateTypeDef State; /*!< DFSDM filter state */ + uint32_t ErrorCode; /*!< DFSDM filter error code */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + void (*AwdCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel, uint32_t Threshold); /*!< DFSDM filter analog watchdog callback */ + void (*RegConvCpltCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter regular conversion complete callback */ + void (*RegConvHalfCpltCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter half regular conversion complete callback */ + void (*InjConvCpltCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter injected conversion complete callback */ + void (*InjConvHalfCpltCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter half injected conversion complete callback */ + void (*ErrorCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter error callback */ + void (*MspInitCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter MSP init callback */ + void (*MspDeInitCallback) (struct __DFSDM_Filter_HandleTypeDef *hdfsdm_filter); /*!< DFSDM filter MSP de-init callback */ +#endif +}DFSDM_Filter_HandleTypeDef; + +/** + * @brief DFSDM filter analog watchdog parameters structure definition + */ +typedef struct +{ + uint32_t DataSource; /*!< Values from digital filter or from channel watchdog filter. + This parameter can be a value of @ref DFSDM_Filter_AwdDataSource */ + uint32_t Channel; /*!< Analog watchdog channel selection. + This parameter can be a values combination of @ref DFSDM_Channel_Selection */ + int32_t HighThreshold; /*!< High threshold for the analog watchdog. + This parameter must be a number between Min_Data = -8388608 and Max_Data = 8388607 */ + int32_t LowThreshold; /*!< Low threshold for the analog watchdog. + This parameter must be a number between Min_Data = -8388608 and Max_Data = 8388607 */ + uint32_t HighBreakSignal; /*!< Break signal assigned to analog watchdog high threshold event. + This parameter can be a values combination of @ref DFSDM_BreakSignals */ + uint32_t LowBreakSignal; /*!< Break signal assigned to analog watchdog low threshold event. + This parameter can be a values combination of @ref DFSDM_BreakSignals */ +}DFSDM_Filter_AwdParamTypeDef; + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/** + * @brief DFSDM filter callback ID enumeration definition + */ +typedef enum +{ + HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID = 0x00U, /*!< DFSDM filter regular conversion complete callback ID */ + HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID = 0x01U, /*!< DFSDM filter half regular conversion complete callback ID */ + HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID = 0x02U, /*!< DFSDM filter injected conversion complete callback ID */ + HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID = 0x03U, /*!< DFSDM filter half injected conversion complete callback ID */ + HAL_DFSDM_FILTER_ERROR_CB_ID = 0x04U, /*!< DFSDM filter error callback ID */ + HAL_DFSDM_FILTER_MSPINIT_CB_ID = 0x05U, /*!< DFSDM filter MSP init callback ID */ + HAL_DFSDM_FILTER_MSPDEINIT_CB_ID = 0x06U /*!< DFSDM filter MSP de-init callback ID */ +}HAL_DFSDM_Filter_CallbackIDTypeDef; + +/** + * @brief DFSDM filter callback pointer definition + */ +typedef void (*pDFSDM_Filter_CallbackTypeDef)(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +typedef void (*pDFSDM_Filter_AwdCallbackTypeDef)(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t Channel, uint32_t Threshold); +#endif + +/** + * @} + */ +#if defined(SYSCFG_MCHDLYCR_BSCKSEL) +/** + * @brief Synchronization parameters structure definition for STM32F413xx/STM32F423xx devices + */ +typedef struct +{ + uint32_t DFSDM1ClockIn; /*!< Source selection for DFSDM1_Ckin. + This parameter can be a value of @ref DFSDM_1_CLOCKIN_SELECTION*/ + uint32_t DFSDM2ClockIn; /*!< Source selection for DFSDM2_Ckin. + This parameter can be a value of @ref DFSDM_2_CLOCKIN_SELECTION*/ + uint32_t DFSDM1ClockOut; /*!< Source selection for DFSDM1_Ckout. + This parameter can be a value of @ref DFSDM_1_CLOCKOUT_SELECTION*/ + uint32_t DFSDM2ClockOut; /*!< Source selection for DFSDM2_Ckout. + This parameter can be a value of @ref DFSDM_2_CLOCKOUT_SELECTION*/ + uint32_t DFSDM1BitClkDistribution; /*!< Distribution of the DFSDM1 bitstream clock gated by TIM4 OC1 or TIM4 OC2. + This parameter can be a value of @ref DFSDM_1_BIT_STREAM_DISTRIBUTION + @note The DFSDM2 audio gated by TIM4 OC2 can be injected on CKIN0 or CKIN2 + @note The DFSDM2 audio gated by TIM4 OC1 can be injected on CKIN1 or CKIN3 */ + uint32_t DFSDM2BitClkDistribution; /*!< Distribution of the DFSDM2 bitstream clock gated by TIM3 OC1 or TIM3 OC2 or TIM3 OC3 or TIM3 OC4. + This parameter can be a value of @ref DFSDM_2_BIT_STREAM_DISTRIBUTION + @note The DFSDM2 audio gated by TIM3 OC4 can be injected on CKIN0 or CKIN4 + @note The DFSDM2 audio gated by TIM3 OC3 can be injected on CKIN1 or CKIN5 + @note The DFSDM2 audio gated by TIM3 OC2 can be injected on CKIN2 or CKIN6 + @note The DFSDM2 audio gated by TIM3 OC1 can be injected on CKIN3 or CKIN7 */ + uint32_t DFSDM1DataDistribution; /*!< Source selection for DatIn0 and DatIn2 of DFSDM1. + This parameter can be a value of @ref DFSDM_1_DATA_DISTRIBUTION */ + uint32_t DFSDM2DataDistribution; /*!< Source selection for DatIn0, DatIn2, DatIn4 and DatIn6 of DFSDM2. + This parameter can be a value of @ref DFSDM_2_DATA_DISTRIBUTION */ +}DFSDM_MultiChannelConfigTypeDef; +#endif /* SYSCFG_MCHDLYCR_BSCKSEL */ +/** + * @} + */ + +/* End of exported types -----------------------------------------------------*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DFSDM_Exported_Constants DFSDM Exported Constants + * @{ + */ + +/** @defgroup DFSDM_Channel_OutputClock DFSDM channel output clock selection + * @{ + */ +#define DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM 0x00000000U /*!< Source for output clock is system clock */ +#define DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO DFSDM_CHCFGR1_CKOUTSRC /*!< Source for output clock is audio clock */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_InputMultiplexer DFSDM channel input multiplexer + * @{ + */ +#define DFSDM_CHANNEL_EXTERNAL_INPUTS 0x00000000U /*!< Data are taken from external inputs */ +#define DFSDM_CHANNEL_INTERNAL_REGISTER DFSDM_CHCFGR1_DATMPX_1 /*!< Data are taken from internal register */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_DataPacking DFSDM channel input data packing + * @{ + */ +#define DFSDM_CHANNEL_STANDARD_MODE 0x00000000U /*!< Standard data packing mode */ +#define DFSDM_CHANNEL_INTERLEAVED_MODE DFSDM_CHCFGR1_DATPACK_0 /*!< Interleaved data packing mode */ +#define DFSDM_CHANNEL_DUAL_MODE DFSDM_CHCFGR1_DATPACK_1 /*!< Dual data packing mode */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_InputPins DFSDM channel input pins + * @{ + */ +#define DFSDM_CHANNEL_SAME_CHANNEL_PINS 0x00000000U /*!< Input from pins on same channel */ +#define DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS DFSDM_CHCFGR1_CHINSEL /*!< Input from pins on following channel */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_SerialInterfaceType DFSDM channel serial interface type + * @{ + */ +#define DFSDM_CHANNEL_SPI_RISING 0x00000000U /*!< SPI with rising edge */ +#define DFSDM_CHANNEL_SPI_FALLING DFSDM_CHCFGR1_SITP_0 /*!< SPI with falling edge */ +#define DFSDM_CHANNEL_MANCHESTER_RISING DFSDM_CHCFGR1_SITP_1 /*!< Manchester with rising edge */ +#define DFSDM_CHANNEL_MANCHESTER_FALLING DFSDM_CHCFGR1_SITP /*!< Manchester with falling edge */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_SpiClock DFSDM channel SPI clock selection + * @{ + */ +#define DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL 0x00000000U /*!< External SPI clock */ +#define DFSDM_CHANNEL_SPI_CLOCK_INTERNAL DFSDM_CHCFGR1_SPICKSEL_0 /*!< Internal SPI clock */ +#define DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING DFSDM_CHCFGR1_SPICKSEL_1 /*!< Internal SPI clock divided by 2, falling edge */ +#define DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING DFSDM_CHCFGR1_SPICKSEL /*!< Internal SPI clock divided by 2, rising edge */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_AwdFilterOrder DFSDM channel analog watchdog filter order + * @{ + */ +#define DFSDM_CHANNEL_FASTSINC_ORDER 0x00000000U /*!< FastSinc filter type */ +#define DFSDM_CHANNEL_SINC1_ORDER DFSDM_CHAWSCDR_AWFORD_0 /*!< Sinc 1 filter type */ +#define DFSDM_CHANNEL_SINC2_ORDER DFSDM_CHAWSCDR_AWFORD_1 /*!< Sinc 2 filter type */ +#define DFSDM_CHANNEL_SINC3_ORDER DFSDM_CHAWSCDR_AWFORD /*!< Sinc 3 filter type */ +/** + * @} + */ + +/** @defgroup DFSDM_Filter_Trigger DFSDM filter conversion trigger + * @{ + */ +#define DFSDM_FILTER_SW_TRIGGER 0x00000000U /*!< Software trigger */ +#define DFSDM_FILTER_SYNC_TRIGGER 0x00000001U /*!< Synchronous with DFSDM_FLT0 */ +#define DFSDM_FILTER_EXT_TRIGGER 0x00000002U /*!< External trigger (only for injected conversion) */ +/** + * @} + */ + +/** @defgroup DFSDM_Filter_ExtTrigger DFSDM filter external trigger + * @{ + */ +#if defined(STM32F413xx) || defined(STM32F423xx) +/* Trigger for stm32f413xx and STM32f423xx devices */ +#define DFSDM_FILTER_EXT_TRIG_TIM1_TRGO 0x00000000U /*!< For All DFSDM1/2 filters */ +#define DFSDM_FILTER_EXT_TRIG_TIM3_TRGO DFSDM_FLTCR1_JEXTSEL_0 /*!< For All DFSDM1/2 filters */ +#define DFSDM_FILTER_EXT_TRIG_TIM8_TRGO DFSDM_FLTCR1_JEXTSEL_1 /*!< For All DFSDM1/2 filters */ +#define DFSDM_FILTER_EXT_TRIG_TIM10_OC1 (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_1) /*!< For DFSDM1 filter 0 and 1 and DFSDM2 filter 0, 1 and 2 */ +#define DFSDM_FILTER_EXT_TRIG_TIM2_TRGO (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_1) /*!< For DFSDM2 filter 3 */ +#define DFSDM_FILTER_EXT_TRIG_TIM4_TRGO DFSDM_FLTCR1_JEXTSEL_2 /*!< For DFSDM1 filter 0 and 1 and DFSDM2 filter 0, 1 and 2 */ +#define DFSDM_FILTER_EXT_TRIG_TIM11_OC1 DFSDM_FLTCR1_JEXTSEL_2 /*!< For DFSDM2 filter 3 */ +#define DFSDM_FILTER_EXT_TRIG_TIM6_TRGO (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_2) /*!< For DFSDM1 filter 0 and 1 and DFSDM2 filter 0 and 1 */ +#define DFSDM_FILTER_EXT_TRIG_TIM7_TRGO (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_2) /*!< For DFSDM2 filter 2 and 3*/ +#define DFSDM_FILTER_EXT_TRIG_EXTI11 (DFSDM_FLTCR1_JEXTSEL_1 | DFSDM_FLTCR1_JEXTSEL_2) /*!< For All DFSDM1/2 filters */ +#define DFSDM_FILTER_EXT_TRIG_EXTI15 DFSDM_FLTCR1_JEXTSEL /*!< For All DFSDM1/2 filters */ +#else +/* Trigger for stm32f412xx devices */ +#define DFSDM_FILTER_EXT_TRIG_TIM1_TRGO 0x00000000U /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_TIM3_TRGO DFSDM_FLTCR1_JEXTSEL_0 /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_TIM8_TRGO DFSDM_FLTCR1_JEXTSEL_1 /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_TIM10_OC1 (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_1) /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_TIM4_TRGO DFSDM_FLTCR1_JEXTSEL_2 /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_TIM6_TRGO (DFSDM_FLTCR1_JEXTSEL_0 | DFSDM_FLTCR1_JEXTSEL_2) /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_EXTI11 (DFSDM_FLTCR1_JEXTSEL_1 | DFSDM_FLTCR1_JEXTSEL_2) /*!< For DFSDM1 filter 0 and 1*/ +#define DFSDM_FILTER_EXT_TRIG_EXTI15 DFSDM_FLTCR1_JEXTSEL /*!< For DFSDM1 filter 0 and 1*/ +#endif +/** + * @} + */ + +/** @defgroup DFSDM_Filter_ExtTriggerEdge DFSDM filter external trigger edge + * @{ + */ +#define DFSDM_FILTER_EXT_TRIG_RISING_EDGE DFSDM_FLTCR1_JEXTEN_0 /*!< External rising edge */ +#define DFSDM_FILTER_EXT_TRIG_FALLING_EDGE DFSDM_FLTCR1_JEXTEN_1 /*!< External falling edge */ +#define DFSDM_FILTER_EXT_TRIG_BOTH_EDGES DFSDM_FLTCR1_JEXTEN /*!< External rising and falling edges */ +/** + * @} + */ + +/** @defgroup DFSDM_Filter_SincOrder DFSDM filter sinc order + * @{ + */ +#define DFSDM_FILTER_FASTSINC_ORDER 0x00000000U /*!< FastSinc filter type */ +#define DFSDM_FILTER_SINC1_ORDER DFSDM_FLTFCR_FORD_0 /*!< Sinc 1 filter type */ +#define DFSDM_FILTER_SINC2_ORDER DFSDM_FLTFCR_FORD_1 /*!< Sinc 2 filter type */ +#define DFSDM_FILTER_SINC3_ORDER (DFSDM_FLTFCR_FORD_0 | DFSDM_FLTFCR_FORD_1) /*!< Sinc 3 filter type */ +#define DFSDM_FILTER_SINC4_ORDER DFSDM_FLTFCR_FORD_2 /*!< Sinc 4 filter type */ +#define DFSDM_FILTER_SINC5_ORDER (DFSDM_FLTFCR_FORD_0 | DFSDM_FLTFCR_FORD_2) /*!< Sinc 5 filter type */ +/** + * @} + */ + +/** @defgroup DFSDM_Filter_AwdDataSource DFSDM filter analog watchdog data source + * @{ + */ +#define DFSDM_FILTER_AWD_FILTER_DATA 0x00000000U /*!< From digital filter */ +#define DFSDM_FILTER_AWD_CHANNEL_DATA DFSDM_FLTCR1_AWFSEL /*!< From analog watchdog channel */ +/** + * @} + */ + +/** @defgroup DFSDM_Filter_ErrorCode DFSDM filter error code + * @{ + */ +#define DFSDM_FILTER_ERROR_NONE 0x00000000U /*!< No error */ +#define DFSDM_FILTER_ERROR_REGULAR_OVERRUN 0x00000001U /*!< Overrun occurs during regular conversion */ +#define DFSDM_FILTER_ERROR_INJECTED_OVERRUN 0x00000002U /*!< Overrun occurs during injected conversion */ +#define DFSDM_FILTER_ERROR_DMA 0x00000003U /*!< DMA error occurs */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +#define DFSDM_FILTER_ERROR_INVALID_CALLBACK 0x00000004U /*!< Invalid callback error occurs */ +#endif +/** + * @} + */ + +/** @defgroup DFSDM_BreakSignals DFSDM break signals + * @{ + */ +#define DFSDM_NO_BREAK_SIGNAL 0x00000000U /*!< No break signal */ +#define DFSDM_BREAK_SIGNAL_0 0x00000001U /*!< Break signal 0 */ +#define DFSDM_BREAK_SIGNAL_1 0x00000002U /*!< Break signal 1 */ +#define DFSDM_BREAK_SIGNAL_2 0x00000004U /*!< Break signal 2 */ +#define DFSDM_BREAK_SIGNAL_3 0x00000008U /*!< Break signal 3 */ +/** + * @} + */ + +/** @defgroup DFSDM_Channel_Selection DFSDM Channel Selection + * @{ + */ +/* DFSDM Channels ------------------------------------------------------------*/ +/* The DFSDM channels are defined as follows: + - in 16-bit LSB the channel mask is set + - in 16-bit MSB the channel number is set + e.g. for channel 3 definition: + - the channel mask is 0x00000008 (bit 3 is set) + - the channel number 3 is 0x00030000 + --> Consequently, channel 3 definition is 0x00000008 | 0x00030000 = 0x00030008 */ +#define DFSDM_CHANNEL_0 0x00000001U +#define DFSDM_CHANNEL_1 0x00010002U +#define DFSDM_CHANNEL_2 0x00020004U +#define DFSDM_CHANNEL_3 0x00030008U +#define DFSDM_CHANNEL_4 0x00040010U /* only for stmm32f413xx and stm32f423xx devices */ +#define DFSDM_CHANNEL_5 0x00050020U /* only for stmm32f413xx and stm32f423xx devices */ +#define DFSDM_CHANNEL_6 0x00060040U /* only for stmm32f413xx and stm32f423xx devices */ +#define DFSDM_CHANNEL_7 0x00070080U /* only for stmm32f413xx and stm32f423xx devices */ +/** + * @} + */ + +/** @defgroup DFSDM_ContinuousMode DFSDM Continuous Mode + * @{ + */ +#define DFSDM_CONTINUOUS_CONV_OFF 0x00000000U /*!< Conversion are not continuous */ +#define DFSDM_CONTINUOUS_CONV_ON 0x00000001U /*!< Conversion are continuous */ +/** + * @} + */ + +/** @defgroup DFSDM_AwdThreshold DFSDM analog watchdog threshold + * @{ + */ +#define DFSDM_AWD_HIGH_THRESHOLD 0x00000000U /*!< Analog watchdog high threshold */ +#define DFSDM_AWD_LOW_THRESHOLD 0x00000001U /*!< Analog watchdog low threshold */ +/** + * @} + */ + +#if defined(SYSCFG_MCHDLYCR_BSCKSEL) +/** @defgroup DFSDM_1_CLOCKOUT_SELECTION DFSDM1 ClockOut Selection + * @{ + */ +#define DFSDM1_CKOUT_DFSDM2_CKOUT 0x00000080U +#define DFSDM1_CKOUT_DFSDM1 0x00000000U +/** + * @} + */ + +/** @defgroup DFSDM_2_CLOCKOUT_SELECTION DFSDM2 ClockOut Selection + * @{ + */ +#define DFSDM2_CKOUT_DFSDM2_CKOUT 0x00040000U +#define DFSDM2_CKOUT_DFSDM2 0x00000000U +/** + * @} + */ + +/** @defgroup DFSDM_1_CLOCKIN_SELECTION DFSDM1 ClockIn Selection + * @{ + */ +#define DFSDM1_CKIN_DFSDM2_CKOUT 0x00000040U +#define DFSDM1_CKIN_PAD 0x00000000U +/** + * @} + */ + +/** @defgroup DFSDM_2_CLOCKIN_SELECTION DFSDM2 ClockIn Selection + * @{ + */ +#define DFSDM2_CKIN_DFSDM2_CKOUT 0x00020000U +#define DFSDM2_CKIN_PAD 0x00000000U +/** + * @} + */ + +/** @defgroup DFSDM_1_BIT_STREAM_DISTRIBUTION DFSDM1 Bit Stream Distribution + * @{ + */ +#define DFSDM1_T4_OC2_BITSTREAM_CKIN0 0x00000000U /* TIM4_OC2 to CLKIN0 */ +#define DFSDM1_T4_OC2_BITSTREAM_CKIN2 SYSCFG_MCHDLYCR_DFSDM1CK02SEL /* TIM4_OC2 to CLKIN2 */ +#define DFSDM1_T4_OC1_BITSTREAM_CKIN3 SYSCFG_MCHDLYCR_DFSDM1CK13SEL /* TIM4_OC1 to CLKIN3 */ +#define DFSDM1_T4_OC1_BITSTREAM_CKIN1 0x00000000U /* TIM4_OC1 to CLKIN1 */ +/** + * @} + */ + +/** @defgroup DFSDM_2_BIT_STREAM_DISTRIBUTION DFSDM12 Bit Stream Distribution + * @{ + */ +#define DFSDM2_T3_OC4_BITSTREAM_CKIN0 0x00000000U /* TIM3_OC4 to CKIN0 */ +#define DFSDM2_T3_OC4_BITSTREAM_CKIN4 SYSCFG_MCHDLYCR_DFSDM2CK04SEL /* TIM3_OC4 to CKIN4 */ +#define DFSDM2_T3_OC3_BITSTREAM_CKIN5 SYSCFG_MCHDLYCR_DFSDM2CK15SEL /* TIM3_OC3 to CKIN5 */ +#define DFSDM2_T3_OC3_BITSTREAM_CKIN1 0x00000000U /* TIM3_OC3 to CKIN1 */ +#define DFSDM2_T3_OC2_BITSTREAM_CKIN6 SYSCFG_MCHDLYCR_DFSDM2CK26SEL /* TIM3_OC2to CKIN6 */ +#define DFSDM2_T3_OC2_BITSTREAM_CKIN2 0x00000000U /* TIM3_OC2 to CKIN2 */ +#define DFSDM2_T3_OC1_BITSTREAM_CKIN3 0x00000000U /* TIM3_OC1 to CKIN3 */ +#define DFSDM2_T3_OC1_BITSTREAM_CKIN7 SYSCFG_MCHDLYCR_DFSDM2CK37SEL /* TIM3_OC1 to CKIN7 */ +/** + * @} + */ + +/** @defgroup DFSDM_1_DATA_DISTRIBUTION DFSDM1 Data Distribution + * @{ + */ +#define DFSDM1_DATIN0_TO_DATIN0_PAD 0x00000000U +#define DFSDM1_DATIN0_TO_DATIN1_PAD SYSCFG_MCHDLYCR_DFSDM1D0SEL +#define DFSDM1_DATIN2_TO_DATIN2_PAD 0x00000000U +#define DFSDM1_DATIN2_TO_DATIN3_PAD SYSCFG_MCHDLYCR_DFSDM1D2SEL +/** + * @} + */ + +/** @defgroup DFSDM_2_DATA_DISTRIBUTION DFSDM2 Data Distribution + * @{ + */ +#define DFSDM2_DATIN0_TO_DATIN0_PAD 0x00000000U +#define DFSDM2_DATIN0_TO_DATIN1_PAD SYSCFG_MCHDLYCR_DFSDM2D0SEL +#define DFSDM2_DATIN2_TO_DATIN2_PAD 0x00000000U +#define DFSDM2_DATIN2_TO_DATIN3_PAD SYSCFG_MCHDLYCR_DFSDM2D2SEL +#define DFSDM2_DATIN4_TO_DATIN4_PAD 0x00000000U +#define DFSDM2_DATIN4_TO_DATIN5_PAD SYSCFG_MCHDLYCR_DFSDM2D4SEL +#define DFSDM2_DATIN6_TO_DATIN6_PAD 0x00000000U +#define DFSDM2_DATIN6_TO_DATIN7_PAD SYSCFG_MCHDLYCR_DFSDM2D6SEL +/** + * @} + */ + +/** @defgroup HAL_MCHDLY_CLOCK HAL MCHDLY Clock enable + * @{ + */ +#define HAL_MCHDLY_CLOCK_DFSDM2 SYSCFG_MCHDLYCR_MCHDLY2EN +#define HAL_MCHDLY_CLOCK_DFSDM1 SYSCFG_MCHDLYCR_MCHDLY1EN +/** + * @} + */ + +/** @defgroup DFSDM_CLOCKIN_SOURCE DFSDM Clock In Source Selection + * @{ + */ +#define HAL_DFSDM2_CKIN_PAD 0x00040000U +#define HAL_DFSDM2_CKIN_DM SYSCFG_MCHDLYCR_DFSDM2CFG +#define HAL_DFSDM1_CKIN_PAD 0x00000000U +#define HAL_DFSDM1_CKIN_DM SYSCFG_MCHDLYCR_DFSDM1CFG +/** + * @} + */ + +/** @defgroup DFSDM_CLOCKOUT_SOURCE DFSDM Clock Source Selection + * @{ + */ +#define HAL_DFSDM2_CKOUT_DFSDM2 0x10000000U +#define HAL_DFSDM2_CKOUT_M27 SYSCFG_MCHDLYCR_DFSDM2CKOSEL +#define HAL_DFSDM1_CKOUT_DFSDM1 0x00000000U +#define HAL_DFSDM1_CKOUT_M27 SYSCFG_MCHDLYCR_DFSDM1CKOSEL +/** + * @} + */ + +/** @defgroup DFSDM_DATAIN0_SOURCE DFSDM Source Selection For DATAIN0 + * @{ + */ +#define HAL_DATAIN0_DFSDM2_PAD 0x10000000U +#define HAL_DATAIN0_DFSDM2_DATAIN1 SYSCFG_MCHDLYCR_DFSDM2D0SEL +#define HAL_DATAIN0_DFSDM1_PAD 0x00000000U +#define HAL_DATAIN0_DFSDM1_DATAIN1 SYSCFG_MCHDLYCR_DFSDM1D0SEL +/** + * @} + */ + +/** @defgroup DFSDM_DATAIN2_SOURCE DFSDM Source Selection For DATAIN2 + * @{ + */ +#define HAL_DATAIN2_DFSDM2_PAD 0x10000000U +#define HAL_DATAIN2_DFSDM2_DATAIN3 SYSCFG_MCHDLYCR_DFSDM2D2SEL +#define HAL_DATAIN2_DFSDM1_PAD 0x00000000U +#define HAL_DATAIN2_DFSDM1_DATAIN3 SYSCFG_MCHDLYCR_DFSDM1D2SEL +/** + * @} + */ + +/** @defgroup DFSDM_DATAIN4_SOURCE DFSDM Source Selection For DATAIN4 + * @{ + */ +#define HAL_DATAIN4_DFSDM2_PAD 0x00000000U +#define HAL_DATAIN4_DFSDM2_DATAIN5 SYSCFG_MCHDLYCR_DFSDM2D4SEL +/** + * @} + */ + +/** @defgroup DFSDM_DATAIN6_SOURCE DFSDM Source Selection For DATAIN6 + * @{ + */ +#define HAL_DATAIN6_DFSDM2_PAD 0x00000000U +#define HAL_DATAIN6_DFSDM2_DATAIN7 SYSCFG_MCHDLYCR_DFSDM2D6SEL +/** + * @} + */ + +/** @defgroup DFSDM1_CLKIN_SOURCE DFSDM1 Source Selection For CLKIN + * @{ + */ +#define HAL_DFSDM1_CLKIN0_TIM4OC2 0x01000000U +#define HAL_DFSDM1_CLKIN2_TIM4OC2 SYSCFG_MCHDLYCR_DFSDM1CK02SEL +#define HAL_DFSDM1_CLKIN1_TIM4OC1 0x02000000U +#define HAL_DFSDM1_CLKIN3_TIM4OC1 SYSCFG_MCHDLYCR_DFSDM1CK13SEL +/** + * @} + */ + +/** @defgroup DFSDM2_CLKIN_SOURCE DFSDM2 Source Selection For CLKIN + * @{ + */ +#define HAL_DFSDM2_CLKIN0_TIM3OC4 0x04000000U +#define HAL_DFSDM2_CLKIN4_TIM3OC4 SYSCFG_MCHDLYCR_DFSDM2CK04SEL +#define HAL_DFSDM2_CLKIN1_TIM3OC3 0x08000000U +#define HAL_DFSDM2_CLKIN5_TIM3OC3 SYSCFG_MCHDLYCR_DFSDM2CK15SEL +#define HAL_DFSDM2_CLKIN2_TIM3OC2 0x10000000U +#define HAL_DFSDM2_CLKIN6_TIM3OC2 SYSCFG_MCHDLYCR_DFSDM2CK26SEL +#define HAL_DFSDM2_CLKIN3_TIM3OC1 0x00000000U +#define HAL_DFSDM2_CLKIN7_TIM3OC1 SYSCFG_MCHDLYCR_DFSDM2CK37SEL +/** + * @} + */ + +#endif /* SYSCFG_MCHDLYCR_BSCKSEL*/ +/** + * @} + */ +/* End of exported constants -------------------------------------------------*/ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup DFSDM_Exported_Macros DFSDM Exported Macros + * @{ + */ + +/** @brief Reset DFSDM channel handle state. + * @param __HANDLE__ DFSDM channel handle. + * @retval None + */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +#define __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_DFSDM_CHANNEL_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_DFSDM_CHANNEL_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DFSDM_CHANNEL_STATE_RESET) +#endif + +/** @brief Reset DFSDM filter handle state. + * @param __HANDLE__ DFSDM filter handle. + * @retval None + */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +#define __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_DFSDM_FILTER_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_DFSDM_FILTER_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DFSDM_FILTER_STATE_RESET) +#endif + +/** + * @} + */ +/* End of exported macros ----------------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DFSDM_Exported_Functions DFSDM Exported Functions + * @{ + */ + +/** @addtogroup DFSDM_Exported_Functions_Group1_Channel Channel initialization and de-initialization functions + * @{ + */ +/* Channel initialization and de-initialization functions *********************/ +HAL_StatusTypeDef HAL_DFSDM_ChannelInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/* Channel callbacks register/unregister functions ****************************/ +HAL_StatusTypeDef HAL_DFSDM_Channel_RegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID, + pDFSDM_Channel_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DFSDM_Channel_UnRegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID); +#endif +/** + * @} + */ + +/** @addtogroup DFSDM_Exported_Functions_Group2_Channel Channel operation functions + * @{ + */ +/* Channel operation functions ************************************************/ +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); + +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t Threshold, uint32_t BreakSignal); +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t Threshold, uint32_t BreakSignal); +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); + +int16_t HAL_DFSDM_ChannelGetAwdValue(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +HAL_StatusTypeDef HAL_DFSDM_ChannelModifyOffset(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, int32_t Offset); + +HAL_StatusTypeDef HAL_DFSDM_ChannelPollForCkab(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t Timeout); +HAL_StatusTypeDef HAL_DFSDM_ChannelPollForScd(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel, uint32_t Timeout); + +void HAL_DFSDM_ChannelCkabCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +void HAL_DFSDM_ChannelScdCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group3_Channel Channel state function + * @{ + */ +/* Channel state function *****************************************************/ +HAL_DFSDM_Channel_StateTypeDef HAL_DFSDM_ChannelGetState(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel); +/** + * @} + */ + +/** @addtogroup DFSDM_Exported_Functions_Group1_Filter Filter initialization and de-initialization functions + * @{ + */ +/* Filter initialization and de-initialization functions *********************/ +HAL_StatusTypeDef HAL_DFSDM_FilterInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/* Filter callbacks register/unregister functions ****************************/ +HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID, + pDFSDM_Filter_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID); +HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + pDFSDM_Filter_AwdCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +#endif +/** + * @} + */ + +/** @addtogroup DFSDM_Exported_Functions_Group2_Filter Filter control functions + * @{ + */ +/* Filter control functions *********************/ +HAL_StatusTypeDef HAL_DFSDM_FilterConfigRegChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel, + uint32_t ContinuousMode); +HAL_StatusTypeDef HAL_DFSDM_FilterConfigInjChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel); +/** + * @} + */ + +/** @addtogroup DFSDM_Exported_Functions_Group3_Filter Filter operation functions + * @{ + */ +/* Filter operation functions *********************/ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, int32_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, int16_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, int32_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, int16_t *pData, uint32_t Length); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterAwdStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + const DFSDM_Filter_AwdParamTypeDef* awdParam); +HAL_StatusTypeDef HAL_DFSDM_FilterAwdStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +HAL_StatusTypeDef HAL_DFSDM_FilterExdStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t Channel); +HAL_StatusTypeDef HAL_DFSDM_FilterExdStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); + +int32_t HAL_DFSDM_FilterGetRegularValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t* Channel); +int32_t HAL_DFSDM_FilterGetInjectedValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t* Channel); +int32_t HAL_DFSDM_FilterGetExdMaxValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t* Channel); +int32_t HAL_DFSDM_FilterGetExdMinValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t* Channel); +uint32_t HAL_DFSDM_FilterGetConvTimeValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter); + +void HAL_DFSDM_IRQHandler(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); + +HAL_StatusTypeDef HAL_DFSDM_FilterPollForRegConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t Timeout); +HAL_StatusTypeDef HAL_DFSDM_FilterPollForInjConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t Timeout); + +void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterInjConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterInjConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +void HAL_DFSDM_FilterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, uint32_t Channel, uint32_t Threshold); +void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +/** + * @} + */ + +/** @addtogroup DFSDM_Exported_Functions_Group4_Filter Filter state functions + * @{ + */ +/* Filter state functions *****************************************************/ +HAL_DFSDM_Filter_StateTypeDef HAL_DFSDM_FilterGetState(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +uint32_t HAL_DFSDM_FilterGetError(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +/** + * @} + */ +/** @addtogroup DFSDM_Exported_Functions_Group5_Filter MultiChannel operation functions + * @{ + */ +#if defined(SYSCFG_MCHDLYCR_BSCKSEL) +void HAL_DFSDM_ConfigMultiChannelDelay(DFSDM_MultiChannelConfigTypeDef* mchdlystruct); +void HAL_DFSDM_BitstreamClock_Start(void); +void HAL_DFSDM_BitstreamClock_Stop(void); +void HAL_DFSDM_DisableDelayClock(uint32_t MCHDLY); +void HAL_DFSDM_EnableDelayClock(uint32_t MCHDLY); +void HAL_DFSDM_ClockIn_SourceSelection(uint32_t source); +void HAL_DFSDM_ClockOut_SourceSelection(uint32_t source); +void HAL_DFSDM_DataIn0_SourceSelection(uint32_t source); +void HAL_DFSDM_DataIn2_SourceSelection(uint32_t source); +void HAL_DFSDM_DataIn4_SourceSelection(uint32_t source); +void HAL_DFSDM_DataIn6_SourceSelection(uint32_t source); +void HAL_DFSDM_BitStreamClkDistribution_Config(uint32_t source); +#endif /* SYSCFG_MCHDLYCR_BSCKSEL */ +/** + * @} + */ +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DFSDM_Private_Macros DFSDM Private Macros +* @{ +*/ +#define IS_DFSDM_CHANNEL_OUTPUT_CLOCK(CLOCK) (((CLOCK) == DFSDM_CHANNEL_OUTPUT_CLOCK_SYSTEM) || \ + ((CLOCK) == DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO)) +#define IS_DFSDM_CHANNEL_OUTPUT_CLOCK_DIVIDER(DIVIDER) ((2U <= (DIVIDER)) && ((DIVIDER) <= 256U)) +#define IS_DFSDM_CHANNEL_INPUT(INPUT) (((INPUT) == DFSDM_CHANNEL_EXTERNAL_INPUTS) || \ + ((INPUT) == DFSDM_CHANNEL_INTERNAL_REGISTER)) +#define IS_DFSDM_CHANNEL_DATA_PACKING(MODE) (((MODE) == DFSDM_CHANNEL_STANDARD_MODE) || \ + ((MODE) == DFSDM_CHANNEL_INTERLEAVED_MODE) || \ + ((MODE) == DFSDM_CHANNEL_DUAL_MODE)) +#define IS_DFSDM_CHANNEL_INPUT_PINS(PINS) (((PINS) == DFSDM_CHANNEL_SAME_CHANNEL_PINS) || \ + ((PINS) == DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS)) +#define IS_DFSDM_CHANNEL_SERIAL_INTERFACE_TYPE(MODE) (((MODE) == DFSDM_CHANNEL_SPI_RISING) || \ + ((MODE) == DFSDM_CHANNEL_SPI_FALLING) || \ + ((MODE) == DFSDM_CHANNEL_MANCHESTER_RISING) || \ + ((MODE) == DFSDM_CHANNEL_MANCHESTER_FALLING)) +#define IS_DFSDM_CHANNEL_SPI_CLOCK(TYPE) (((TYPE) == DFSDM_CHANNEL_SPI_CLOCK_EXTERNAL) || \ + ((TYPE) == DFSDM_CHANNEL_SPI_CLOCK_INTERNAL) || \ + ((TYPE) == DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_FALLING) || \ + ((TYPE) == DFSDM_CHANNEL_SPI_CLOCK_INTERNAL_DIV2_RISING)) +#define IS_DFSDM_CHANNEL_FILTER_ORDER(ORDER) (((ORDER) == DFSDM_CHANNEL_FASTSINC_ORDER) || \ + ((ORDER) == DFSDM_CHANNEL_SINC1_ORDER) || \ + ((ORDER) == DFSDM_CHANNEL_SINC2_ORDER) || \ + ((ORDER) == DFSDM_CHANNEL_SINC3_ORDER)) +#define IS_DFSDM_CHANNEL_FILTER_OVS_RATIO(RATIO) ((1U <= (RATIO)) && ((RATIO) <= 32U)) +#define IS_DFSDM_CHANNEL_OFFSET(VALUE) ((-8388608 <= (VALUE)) && ((VALUE) <= 8388607)) +#define IS_DFSDM_CHANNEL_RIGHT_BIT_SHIFT(VALUE) ((VALUE) <= 0x1FU) +#define IS_DFSDM_CHANNEL_SCD_THRESHOLD(VALUE) ((VALUE) <= 0xFFU) +#define IS_DFSDM_FILTER_REG_TRIGGER(TRIG) (((TRIG) == DFSDM_FILTER_SW_TRIGGER) || \ + ((TRIG) == DFSDM_FILTER_SYNC_TRIGGER)) +#define IS_DFSDM_FILTER_INJ_TRIGGER(TRIG) (((TRIG) == DFSDM_FILTER_SW_TRIGGER) || \ + ((TRIG) == DFSDM_FILTER_SYNC_TRIGGER) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIGGER)) +#if defined (STM32F413xx) || defined (STM32F423xx) +#define IS_DFSDM_FILTER_EXT_TRIG(TRIG) (((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM1_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM3_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM8_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM10_OC1) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM2_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM4_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM11_OC1) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM6_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_EXTI11) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_EXTI15)) +#define IS_DFSDM_DELAY_CLOCK(CLOCK) (((CLOCK) == HAL_MCHDLY_CLOCK_DFSDM2) || \ + ((CLOCK) == HAL_MCHDLY_CLOCK_DFSDM1)) +#else +#define IS_DFSDM_FILTER_EXT_TRIG(TRIG) (((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM1_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM3_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM8_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM10_OC1) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM4_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_TIM6_TRGO) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_EXTI11) || \ + ((TRIG) == DFSDM_FILTER_EXT_TRIG_EXTI15)) +#endif +#define IS_DFSDM_FILTER_EXT_TRIG_EDGE(EDGE) (((EDGE) == DFSDM_FILTER_EXT_TRIG_RISING_EDGE) || \ + ((EDGE) == DFSDM_FILTER_EXT_TRIG_FALLING_EDGE) || \ + ((EDGE) == DFSDM_FILTER_EXT_TRIG_BOTH_EDGES)) +#define IS_DFSDM_FILTER_SINC_ORDER(ORDER) (((ORDER) == DFSDM_FILTER_FASTSINC_ORDER) || \ + ((ORDER) == DFSDM_FILTER_SINC1_ORDER) || \ + ((ORDER) == DFSDM_FILTER_SINC2_ORDER) || \ + ((ORDER) == DFSDM_FILTER_SINC3_ORDER) || \ + ((ORDER) == DFSDM_FILTER_SINC4_ORDER) || \ + ((ORDER) == DFSDM_FILTER_SINC5_ORDER)) +#define IS_DFSDM_FILTER_OVS_RATIO(RATIO) ((1U <= (RATIO)) && ((RATIO) <= 1024U)) +#define IS_DFSDM_FILTER_INTEGRATOR_OVS_RATIO(RATIO) ((1U <= (RATIO)) && ((RATIO) <= 256U)) +#define IS_DFSDM_FILTER_AWD_DATA_SOURCE(DATA) (((DATA) == DFSDM_FILTER_AWD_FILTER_DATA) || \ + ((DATA) == DFSDM_FILTER_AWD_CHANNEL_DATA)) +#define IS_DFSDM_FILTER_AWD_THRESHOLD(VALUE) ((-8388608 <= (VALUE)) && ((VALUE) <= 8388607)) +#define IS_DFSDM_BREAK_SIGNALS(VALUE) ((VALUE) <= 0x0FU) +#if defined(DFSDM2_Channel0) +#define IS_DFSDM_REGULAR_CHANNEL(CHANNEL) (((CHANNEL) == DFSDM_CHANNEL_0) || \ + ((CHANNEL) == DFSDM_CHANNEL_1) || \ + ((CHANNEL) == DFSDM_CHANNEL_2) || \ + ((CHANNEL) == DFSDM_CHANNEL_3) || \ + ((CHANNEL) == DFSDM_CHANNEL_4) || \ + ((CHANNEL) == DFSDM_CHANNEL_5) || \ + ((CHANNEL) == DFSDM_CHANNEL_6) || \ + ((CHANNEL) == DFSDM_CHANNEL_7)) +#define IS_DFSDM_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) != 0U) && ((CHANNEL) <= 0x000F00FFU)) +#else +#define IS_DFSDM_REGULAR_CHANNEL(CHANNEL) (((CHANNEL) == DFSDM_CHANNEL_0) || \ + ((CHANNEL) == DFSDM_CHANNEL_1) || \ + ((CHANNEL) == DFSDM_CHANNEL_2) || \ + ((CHANNEL) == DFSDM_CHANNEL_3)) +#define IS_DFSDM_INJECTED_CHANNEL(CHANNEL) (((CHANNEL) != 0U) && ((CHANNEL) <= 0x0003000FU)) +#endif +#define IS_DFSDM_CONTINUOUS_MODE(MODE) (((MODE) == DFSDM_CONTINUOUS_CONV_OFF) || \ + ((MODE) == DFSDM_CONTINUOUS_CONV_ON)) +#if defined(DFSDM2_Channel0) +#define IS_DFSDM1_CHANNEL_INSTANCE(INSTANCE) (((INSTANCE) == DFSDM1_Channel0) || \ + ((INSTANCE) == DFSDM1_Channel1) || \ + ((INSTANCE) == DFSDM1_Channel2) || \ + ((INSTANCE) == DFSDM1_Channel3)) +#define IS_DFSDM1_FILTER_INSTANCE(INSTANCE) (((INSTANCE) == DFSDM1_Filter0) || \ + ((INSTANCE) == DFSDM1_Filter1)) +#endif /* DFSDM2_Channel0 */ + +#if defined(SYSCFG_MCHDLYCR_BSCKSEL) +#define IS_DFSDM_CLOCKIN_SELECTION(SELECTION) (((SELECTION) == HAL_DFSDM2_CKIN_PAD) || \ + ((SELECTION) == HAL_DFSDM2_CKIN_DM) || \ + ((SELECTION) == HAL_DFSDM1_CKIN_PAD) || \ + ((SELECTION) == HAL_DFSDM1_CKIN_DM)) +#define IS_DFSDM_CLOCKOUT_SELECTION(SELECTION) (((SELECTION) == HAL_DFSDM2_CKOUT_DFSDM2) || \ + ((SELECTION) == HAL_DFSDM2_CKOUT_M27) || \ + ((SELECTION) == HAL_DFSDM1_CKOUT_DFSDM1) || \ + ((SELECTION) == HAL_DFSDM1_CKOUT_M27)) +#define IS_DFSDM_DATAIN0_SRC_SELECTION(SELECTION) (((SELECTION) == HAL_DATAIN0_DFSDM2_PAD) || \ + ((SELECTION) == HAL_DATAIN0_DFSDM2_DATAIN1) || \ + ((SELECTION) == HAL_DATAIN0_DFSDM1_PAD) || \ + ((SELECTION) == HAL_DATAIN0_DFSDM1_DATAIN1)) +#define IS_DFSDM_DATAIN2_SRC_SELECTION(SELECTION) (((SELECTION) == HAL_DATAIN2_DFSDM2_PAD) || \ + ((SELECTION) == HAL_DATAIN2_DFSDM2_DATAIN3) || \ + ((SELECTION) == HAL_DATAIN2_DFSDM1_PAD) || \ + ((SELECTION) == HAL_DATAIN2_DFSDM1_DATAIN3)) +#define IS_DFSDM_DATAIN4_SRC_SELECTION(SELECTION) (((SELECTION) == HAL_DATAIN4_DFSDM2_PAD) || \ + ((SELECTION) == HAL_DATAIN4_DFSDM2_DATAIN5)) +#define IS_DFSDM_DATAIN6_SRC_SELECTION(SELECTION) (((SELECTION) == HAL_DATAIN6_DFSDM2_PAD) || \ + ((SELECTION) == HAL_DATAIN6_DFSDM2_DATAIN7)) +#define IS_DFSDM_BITSTREM_CLK_DISTRIBUTION(DISTRIBUTION) (((DISTRIBUTION) == HAL_DFSDM1_CLKIN0_TIM4OC2) || \ + ((DISTRIBUTION) == HAL_DFSDM1_CLKIN2_TIM4OC2) || \ + ((DISTRIBUTION) == HAL_DFSDM1_CLKIN1_TIM4OC1) || \ + ((DISTRIBUTION) == HAL_DFSDM1_CLKIN3_TIM4OC1) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN0_TIM3OC4) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN4_TIM3OC4) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN1_TIM3OC3)|| \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN5_TIM3OC3) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN2_TIM3OC2) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN6_TIM3OC2) || \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN3_TIM3OC1)|| \ + ((DISTRIBUTION) == HAL_DFSDM2_CLKIN7_TIM3OC1)) +#define IS_DFSDM_DFSDM1_CLKOUT(CLKOUT) (((CLKOUT) == DFSDM1_CKOUT_DFSDM2_CKOUT) || \ + ((CLKOUT) == DFSDM1_CKOUT_DFSDM1)) +#define IS_DFSDM_DFSDM2_CLKOUT(CLKOUT) (((CLKOUT) == DFSDM2_CKOUT_DFSDM2_CKOUT) || \ + ((CLKOUT) == DFSDM2_CKOUT_DFSDM2)) +#define IS_DFSDM_DFSDM1_CLKIN(CLKIN) (((CLKIN) == DFSDM1_CKIN_DFSDM2_CKOUT) || \ + ((CLKIN) == DFSDM1_CKIN_PAD)) +#define IS_DFSDM_DFSDM2_CLKIN(CLKIN) (((CLKIN) == DFSDM2_CKIN_DFSDM2_CKOUT) || \ + ((CLKIN) == DFSDM2_CKIN_PAD)) +#define IS_DFSDM_DFSDM1_BIT_CLK(CLK) (((CLK) == DFSDM1_T4_OC2_BITSTREAM_CKIN0) || \ + ((CLK) == DFSDM1_T4_OC2_BITSTREAM_CKIN2) || \ + ((CLK) == DFSDM1_T4_OC1_BITSTREAM_CKIN3) || \ + ((CLK) == DFSDM1_T4_OC1_BITSTREAM_CKIN1) || \ + ((CLK) <= 0x30U)) + +#define IS_DFSDM_DFSDM2_BIT_CLK(CLK) (((CLK) == DFSDM2_T3_OC4_BITSTREAM_CKIN0) || \ + ((CLK) == DFSDM2_T3_OC4_BITSTREAM_CKIN4) || \ + ((CLK) == DFSDM2_T3_OC3_BITSTREAM_CKIN5) || \ + ((CLK) == DFSDM2_T3_OC3_BITSTREAM_CKIN1) || \ + ((CLK) == DFSDM2_T3_OC2_BITSTREAM_CKIN6) || \ + ((CLK) == DFSDM2_T3_OC2_BITSTREAM_CKIN2) || \ + ((CLK) == DFSDM2_T3_OC1_BITSTREAM_CKIN3) || \ + ((CLK) == DFSDM2_T3_OC1_BITSTREAM_CKIN7)|| \ + ((CLK) <= 0x1E000U)) + +#define IS_DFSDM_DFSDM1_DATA_DISTRIBUTION(DISTRIBUTION)(((DISTRIBUTION) == DFSDM1_DATIN0_TO_DATIN0_PAD )|| \ + ((DISTRIBUTION) == DFSDM1_DATIN0_TO_DATIN1_PAD) || \ + ((DISTRIBUTION) == DFSDM1_DATIN2_TO_DATIN2_PAD) || \ + ((DISTRIBUTION) == DFSDM1_DATIN2_TO_DATIN3_PAD)|| \ + ((DISTRIBUTION) <= 0xCU)) + +#define IS_DFSDM_DFSDM2_DATA_DISTRIBUTION(DISTRIBUTION)(((DISTRIBUTION) == DFSDM2_DATIN0_TO_DATIN0_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN0_TO_DATIN1_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN2_TO_DATIN2_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN2_TO_DATIN3_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN4_TO_DATIN4_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN4_TO_DATIN5_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN6_TO_DATIN6_PAD)|| \ + ((DISTRIBUTION) == DFSDM2_DATIN6_TO_DATIN7_PAD)|| \ + ((DISTRIBUTION) <= 0x1D00U)) +#endif /* (SYSCFG_MCHDLYCR_BSCKSEL) */ +/** + * @} + */ +/* End of private macros -----------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ +#endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_DFSDM_H */ diff --git a/libs/hal/stm32f4xx_hal_dma.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h similarity index 100% rename from libs/hal/stm32f4xx_hal_dma.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h new file mode 100644 index 0000000..8967141 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma2d.h @@ -0,0 +1,638 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dma2d.h + * @author MCD Application Team + * @brief Header file of DMA2D 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 STM32F4xx_HAL_DMA2D_H +#define STM32F4xx_HAL_DMA2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined (DMA2D) + +/** @addtogroup DMA2D DMA2D + * @brief DMA2D HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DMA2D_Exported_Types DMA2D Exported Types + * @{ + */ +#define MAX_DMA2D_LAYER 2U /*!< DMA2D maximum number of layers */ + +/** + * @brief DMA2D CLUT Structure definition + */ +typedef struct +{ + uint32_t *pCLUT; /*!< Configures the DMA2D CLUT memory address.*/ + + uint32_t CLUTColorMode; /*!< Configures the DMA2D CLUT color mode. + This parameter can be one value of @ref DMA2D_CLUT_CM. */ + + uint32_t Size; /*!< Configures the DMA2D CLUT size. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF.*/ +} DMA2D_CLUTCfgTypeDef; + +/** + * @brief DMA2D Init structure definition + */ +typedef struct +{ + uint32_t Mode; /*!< Configures the DMA2D transfer mode. + This parameter can be one value of @ref DMA2D_Mode. */ + + uint32_t ColorMode; /*!< Configures the color format of the output image. + This parameter can be one value of @ref DMA2D_Output_Color_Mode. */ + + uint32_t OutputOffset; /*!< Specifies the Offset value. + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0x3FFF. */ + + + + +} DMA2D_InitTypeDef; + + +/** + * @brief DMA2D Layer structure definition + */ +typedef struct +{ + uint32_t InputOffset; /*!< Configures the DMA2D foreground or background offset. + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0x3FFF. */ + + uint32_t InputColorMode; /*!< Configures the DMA2D foreground or background color mode. + This parameter can be one value of @ref DMA2D_Input_Color_Mode. */ + + uint32_t AlphaMode; /*!< Configures the DMA2D foreground or background alpha mode. + This parameter can be one value of @ref DMA2D_Alpha_Mode. */ + + uint32_t InputAlpha; /*!< Specifies the DMA2D foreground or background alpha value and color value + in case of A8 or A4 color mode. + This parameter must be a number between Min_Data = 0x00 + and Max_Data = 0xFF except for the color modes detailed below. + @note In case of A8 or A4 color mode (ARGB), + this parameter must be a number between + Min_Data = 0x00000000 and Max_Data = 0xFFFFFFFF where + - InputAlpha[24:31] is the alpha value ALPHA[0:7] + - InputAlpha[16:23] is the red value RED[0:7] + - InputAlpha[8:15] is the green value GREEN[0:7] + - InputAlpha[0:7] is the blue value BLUE[0:7]. */ + + +} DMA2D_LayerCfgTypeDef; + +/** + * @brief HAL DMA2D State structures definition + */ +typedef enum +{ + HAL_DMA2D_STATE_RESET = 0x00U, /*!< DMA2D not yet initialized or disabled */ + HAL_DMA2D_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_DMA2D_STATE_BUSY = 0x02U, /*!< An internal process is ongoing */ + HAL_DMA2D_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ + HAL_DMA2D_STATE_ERROR = 0x04U, /*!< DMA2D state error */ + HAL_DMA2D_STATE_SUSPEND = 0x05U /*!< DMA2D process is suspended */ +} HAL_DMA2D_StateTypeDef; + +/** + * @brief DMA2D handle Structure definition + */ +typedef struct __DMA2D_HandleTypeDef +{ + DMA2D_TypeDef *Instance; /*!< DMA2D register base address. */ + + DMA2D_InitTypeDef Init; /*!< DMA2D communication parameters. */ + + void (* XferCpltCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D transfer complete callback. */ + + void (* XferErrorCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D transfer error callback. */ + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) + void (* LineEventCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D line event callback. */ + + void (* CLUTLoadingCpltCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D CLUT loading completion callback */ + + void (* MspInitCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D Msp Init callback. */ + + void (* MspDeInitCallback)(struct __DMA2D_HandleTypeDef *hdma2d); /*!< DMA2D Msp DeInit callback. */ + +#endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */ + + DMA2D_LayerCfgTypeDef LayerCfg[MAX_DMA2D_LAYER]; /*!< DMA2D Layers parameters */ + + HAL_LockTypeDef Lock; /*!< DMA2D lock. */ + + __IO HAL_DMA2D_StateTypeDef State; /*!< DMA2D transfer state. */ + + __IO uint32_t ErrorCode; /*!< DMA2D error code. */ +} DMA2D_HandleTypeDef; + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +/** + * @brief HAL DMA2D Callback pointer definition + */ +typedef void (*pDMA2D_CallbackTypeDef)(DMA2D_HandleTypeDef *hdma2d); /*!< Pointer to a DMA2D common callback function */ +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMA2D_Exported_Constants DMA2D Exported Constants + * @{ + */ + +/** @defgroup DMA2D_Error_Code DMA2D Error Code + * @{ + */ +#define HAL_DMA2D_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_DMA2D_ERROR_TE 0x00000001U /*!< Transfer error */ +#define HAL_DMA2D_ERROR_CE 0x00000002U /*!< Configuration error */ +#define HAL_DMA2D_ERROR_CAE 0x00000004U /*!< CLUT access error */ +#define HAL_DMA2D_ERROR_TIMEOUT 0x00000020U /*!< Timeout error */ +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +#define HAL_DMA2D_ERROR_INVALID_CALLBACK 0x00000040U /*!< Invalid callback error */ +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup DMA2D_Mode DMA2D Mode + * @{ + */ +#define DMA2D_M2M 0x00000000U /*!< DMA2D memory to memory transfer mode */ +#define DMA2D_M2M_PFC DMA2D_CR_MODE_0 /*!< DMA2D memory to memory with pixel format conversion transfer mode */ +#define DMA2D_M2M_BLEND DMA2D_CR_MODE_1 /*!< DMA2D memory to memory with blending transfer mode */ +#define DMA2D_R2M DMA2D_CR_MODE /*!< DMA2D register to memory transfer mode */ +/** + * @} + */ + +/** @defgroup DMA2D_Output_Color_Mode DMA2D Output Color Mode + * @{ + */ +#define DMA2D_OUTPUT_ARGB8888 0x00000000U /*!< ARGB8888 DMA2D color mode */ +#define DMA2D_OUTPUT_RGB888 DMA2D_OPFCCR_CM_0 /*!< RGB888 DMA2D color mode */ +#define DMA2D_OUTPUT_RGB565 DMA2D_OPFCCR_CM_1 /*!< RGB565 DMA2D color mode */ +#define DMA2D_OUTPUT_ARGB1555 (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /*!< ARGB1555 DMA2D color mode */ +#define DMA2D_OUTPUT_ARGB4444 DMA2D_OPFCCR_CM_2 /*!< ARGB4444 DMA2D color mode */ +/** + * @} + */ + +/** @defgroup DMA2D_Input_Color_Mode DMA2D Input Color Mode + * @{ + */ +#define DMA2D_INPUT_ARGB8888 0x00000000U /*!< ARGB8888 color mode */ +#define DMA2D_INPUT_RGB888 0x00000001U /*!< RGB888 color mode */ +#define DMA2D_INPUT_RGB565 0x00000002U /*!< RGB565 color mode */ +#define DMA2D_INPUT_ARGB1555 0x00000003U /*!< ARGB1555 color mode */ +#define DMA2D_INPUT_ARGB4444 0x00000004U /*!< ARGB4444 color mode */ +#define DMA2D_INPUT_L8 0x00000005U /*!< L8 color mode */ +#define DMA2D_INPUT_AL44 0x00000006U /*!< AL44 color mode */ +#define DMA2D_INPUT_AL88 0x00000007U /*!< AL88 color mode */ +#define DMA2D_INPUT_L4 0x00000008U /*!< L4 color mode */ +#define DMA2D_INPUT_A8 0x00000009U /*!< A8 color mode */ +#define DMA2D_INPUT_A4 0x0000000AU /*!< A4 color mode */ +/** + * @} + */ + +/** @defgroup DMA2D_Alpha_Mode DMA2D Alpha Mode + * @{ + */ +#define DMA2D_NO_MODIF_ALPHA 0x00000000U /*!< No modification of the alpha channel value */ +#define DMA2D_REPLACE_ALPHA 0x00000001U /*!< Replace original alpha channel value by programmed alpha value */ +#define DMA2D_COMBINE_ALPHA 0x00000002U /*!< Replace original alpha channel value by programmed alpha value + with original alpha channel value */ +/** + * @} + */ + + + + + + +/** @defgroup DMA2D_CLUT_CM DMA2D CLUT Color Mode + * @{ + */ +#define DMA2D_CCM_ARGB8888 0x00000000U /*!< ARGB8888 DMA2D CLUT color mode */ +#define DMA2D_CCM_RGB888 0x00000001U /*!< RGB888 DMA2D CLUT color mode */ +/** + * @} + */ + +/** @defgroup DMA2D_Interrupts DMA2D Interrupts + * @{ + */ +#define DMA2D_IT_CE DMA2D_CR_CEIE /*!< Configuration Error Interrupt */ +#define DMA2D_IT_CTC DMA2D_CR_CTCIE /*!< CLUT Transfer Complete Interrupt */ +#define DMA2D_IT_CAE DMA2D_CR_CAEIE /*!< CLUT Access Error Interrupt */ +#define DMA2D_IT_TW DMA2D_CR_TWIE /*!< Transfer Watermark Interrupt */ +#define DMA2D_IT_TC DMA2D_CR_TCIE /*!< Transfer Complete Interrupt */ +#define DMA2D_IT_TE DMA2D_CR_TEIE /*!< Transfer Error Interrupt */ +/** + * @} + */ + +/** @defgroup DMA2D_Flags DMA2D Flags + * @{ + */ +#define DMA2D_FLAG_CE DMA2D_ISR_CEIF /*!< Configuration Error Interrupt Flag */ +#define DMA2D_FLAG_CTC DMA2D_ISR_CTCIF /*!< CLUT Transfer Complete Interrupt Flag */ +#define DMA2D_FLAG_CAE DMA2D_ISR_CAEIF /*!< CLUT Access Error Interrupt Flag */ +#define DMA2D_FLAG_TW DMA2D_ISR_TWIF /*!< Transfer Watermark Interrupt Flag */ +#define DMA2D_FLAG_TC DMA2D_ISR_TCIF /*!< Transfer Complete Interrupt Flag */ +#define DMA2D_FLAG_TE DMA2D_ISR_TEIF /*!< Transfer Error Interrupt Flag */ +/** + * @} + */ + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +/** + * @brief HAL DMA2D common Callback ID enumeration definition + */ +typedef enum +{ + HAL_DMA2D_MSPINIT_CB_ID = 0x00U, /*!< DMA2D MspInit callback ID */ + HAL_DMA2D_MSPDEINIT_CB_ID = 0x01U, /*!< DMA2D MspDeInit callback ID */ + HAL_DMA2D_TRANSFERCOMPLETE_CB_ID = 0x02U, /*!< DMA2D transfer complete callback ID */ + HAL_DMA2D_TRANSFERERROR_CB_ID = 0x03U, /*!< DMA2D transfer error callback ID */ + HAL_DMA2D_LINEEVENT_CB_ID = 0x04U, /*!< DMA2D line event callback ID */ + HAL_DMA2D_CLUTLOADINGCPLT_CB_ID = 0x05U, /*!< DMA2D CLUT loading completion callback ID */ +} HAL_DMA2D_CallbackIDTypeDef; +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + + +/** + * @} + */ +/* Exported macros ------------------------------------------------------------*/ +/** @defgroup DMA2D_Exported_Macros DMA2D Exported Macros + * @{ + */ + +/** @brief Reset DMA2D handle state + * @param __HANDLE__ specifies the DMA2D handle. + * @retval None + */ +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +#define __HAL_DMA2D_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_DMA2D_STATE_RESET;\ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + }while(0) +#else +#define __HAL_DMA2D_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DMA2D_STATE_RESET) +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + + +/** + * @brief Enable the DMA2D. + * @param __HANDLE__ DMA2D handle + * @retval None. + */ +#define __HAL_DMA2D_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= DMA2D_CR_START) + + +/* Interrupt & Flag management */ +/** + * @brief Get the DMA2D pending flags. + * @param __HANDLE__ DMA2D handle + * @param __FLAG__ flag to check. + * This parameter can be any combination of the following values: + * @arg DMA2D_FLAG_CE: Configuration error flag + * @arg DMA2D_FLAG_CTC: CLUT transfer complete flag + * @arg DMA2D_FLAG_CAE: CLUT access error flag + * @arg DMA2D_FLAG_TW: Transfer Watermark flag + * @arg DMA2D_FLAG_TC: Transfer complete flag + * @arg DMA2D_FLAG_TE: Transfer error flag + * @retval The state of FLAG. + */ +#define __HAL_DMA2D_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR & (__FLAG__)) + +/** + * @brief Clear the DMA2D pending flags. + * @param __HANDLE__ DMA2D handle + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DMA2D_FLAG_CE: Configuration error flag + * @arg DMA2D_FLAG_CTC: CLUT transfer complete flag + * @arg DMA2D_FLAG_CAE: CLUT access error flag + * @arg DMA2D_FLAG_TW: Transfer Watermark flag + * @arg DMA2D_FLAG_TC: Transfer complete flag + * @arg DMA2D_FLAG_TE: Transfer error flag + * @retval None + */ +#define __HAL_DMA2D_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->IFCR = (__FLAG__)) + +/** + * @brief Enable the specified DMA2D interrupts. + * @param __HANDLE__ DMA2D handle + * @param __INTERRUPT__ specifies the DMA2D interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg DMA2D_IT_CE: Configuration error interrupt mask + * @arg DMA2D_IT_CTC: CLUT transfer complete interrupt mask + * @arg DMA2D_IT_CAE: CLUT access error interrupt mask + * @arg DMA2D_IT_TW: Transfer Watermark interrupt mask + * @arg DMA2D_IT_TC: Transfer complete interrupt mask + * @arg DMA2D_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA2D_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the specified DMA2D interrupts. + * @param __HANDLE__ DMA2D handle + * @param __INTERRUPT__ specifies the DMA2D interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg DMA2D_IT_CE: Configuration error interrupt mask + * @arg DMA2D_IT_CTC: CLUT transfer complete interrupt mask + * @arg DMA2D_IT_CAE: CLUT access error interrupt mask + * @arg DMA2D_IT_TW: Transfer Watermark interrupt mask + * @arg DMA2D_IT_TC: Transfer complete interrupt mask + * @arg DMA2D_IT_TE: Transfer error interrupt mask + * @retval None + */ +#define __HAL_DMA2D_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified DMA2D interrupt source is enabled or not. + * @param __HANDLE__ DMA2D handle + * @param __INTERRUPT__ specifies the DMA2D interrupt source to check. + * This parameter can be one of the following values: + * @arg DMA2D_IT_CE: Configuration error interrupt mask + * @arg DMA2D_IT_CTC: CLUT transfer complete interrupt mask + * @arg DMA2D_IT_CAE: CLUT access error interrupt mask + * @arg DMA2D_IT_TW: Transfer Watermark interrupt mask + * @arg DMA2D_IT_TC: Transfer complete interrupt mask + * @arg DMA2D_IT_TE: Transfer error interrupt mask + * @retval The state of INTERRUPT source. + */ +#define __HAL_DMA2D_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR & (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DMA2D_Exported_Functions DMA2D Exported Functions + * @{ + */ + +/** @addtogroup DMA2D_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions *******************************/ +HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_DeInit(DMA2D_HandleTypeDef *hdma2d); +void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef *hdma2d); +void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef *hdma2d); +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_DMA2D_RegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID, + pDMA2D_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DMA2D_UnRegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + +/** + * @} + */ + + +/** @addtogroup DMA2D_Exported_Functions_Group2 IO operation functions + * @{ + */ + +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_DMA2D_Start(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height); +HAL_StatusTypeDef HAL_DMA2D_BlendingStart(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, + uint32_t DstAddress, uint32_t Width, uint32_t Height); +HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height); +HAL_StatusTypeDef HAL_DMA2D_BlendingStart_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, + uint32_t DstAddress, uint32_t Width, uint32_t Height); +HAL_StatusTypeDef HAL_DMA2D_Suspend(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_Resume(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_Abort(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_EnableCLUT(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, + uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, + uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Abort(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Suspend(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Resume(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_PollForTransfer(DMA2D_HandleTypeDef *hdma2d, uint32_t Timeout); +void HAL_DMA2D_IRQHandler(DMA2D_HandleTypeDef *hdma2d); +void HAL_DMA2D_LineEventCallback(DMA2D_HandleTypeDef *hdma2d); +void HAL_DMA2D_CLUTLoadingCpltCallback(DMA2D_HandleTypeDef *hdma2d); + +/** + * @} + */ + +/** @addtogroup DMA2D_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ + +/* Peripheral Control functions *************************************************/ +HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_ConfigCLUT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_DMA2D_ProgramLineEvent(DMA2D_HandleTypeDef *hdma2d, uint32_t Line); +HAL_StatusTypeDef HAL_DMA2D_EnableDeadTime(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_DisableDeadTime(DMA2D_HandleTypeDef *hdma2d); +HAL_StatusTypeDef HAL_DMA2D_ConfigDeadTime(DMA2D_HandleTypeDef *hdma2d, uint8_t DeadTime); + +/** + * @} + */ + +/** @addtogroup DMA2D_Exported_Functions_Group4 Peripheral State and Error functions + * @{ + */ + +/* Peripheral State functions ***************************************************/ +HAL_DMA2D_StateTypeDef HAL_DMA2D_GetState(DMA2D_HandleTypeDef *hdma2d); +uint32_t HAL_DMA2D_GetError(DMA2D_HandleTypeDef *hdma2d); + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ + +/** @addtogroup DMA2D_Private_Constants DMA2D Private Constants + * @{ + */ + +/** @defgroup DMA2D_Maximum_Line_WaterMark DMA2D Maximum Line Watermark + * @{ + */ +#define DMA2D_LINE_WATERMARK_MAX DMA2D_LWR_LW /*!< DMA2D maximum line watermark */ +/** + * @} + */ + +/** @defgroup DMA2D_Color_Value DMA2D Color Value + * @{ + */ +#define DMA2D_COLOR_VALUE 0x000000FFU /*!< Color value mask */ +/** + * @} + */ + +/** @defgroup DMA2D_Max_Layer DMA2D Maximum Number of Layers + * @{ + */ +#define DMA2D_MAX_LAYER 2U /*!< DMA2D maximum number of layers */ +/** + * @} + */ + +/** @defgroup DMA2D_Layers DMA2D Layers + * @{ + */ +#define DMA2D_BACKGROUND_LAYER 0x00000000U /*!< DMA2D Background Layer (layer 0) */ +#define DMA2D_FOREGROUND_LAYER 0x00000001U /*!< DMA2D Foreground Layer (layer 1) */ +/** + * @} + */ + +/** @defgroup DMA2D_Offset DMA2D Offset + * @{ + */ +#define DMA2D_OFFSET DMA2D_FGOR_LO /*!< maximum Line Offset */ +/** + * @} + */ + +/** @defgroup DMA2D_Size DMA2D Size + * @{ + */ +#define DMA2D_PIXEL (DMA2D_NLR_PL >> 16U) /*!< DMA2D maximum number of pixels per line */ +#define DMA2D_LINE DMA2D_NLR_NL /*!< DMA2D maximum number of lines */ +/** + * @} + */ + +/** @defgroup DMA2D_CLUT_Size DMA2D CLUT Size + * @{ + */ +#define DMA2D_CLUT_SIZE (DMA2D_FGPFCCR_CS >> 8U) /*!< DMA2D maximum CLUT size */ +/** + * @} + */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DMA2D_Private_Macros DMA2D Private Macros + * @{ + */ +#define IS_DMA2D_LAYER(LAYER) (((LAYER) == DMA2D_BACKGROUND_LAYER)\ + || ((LAYER) == DMA2D_FOREGROUND_LAYER)) + +#define IS_DMA2D_MODE(MODE) (((MODE) == DMA2D_M2M) || ((MODE) == DMA2D_M2M_PFC) || \ + ((MODE) == DMA2D_M2M_BLEND) || ((MODE) == DMA2D_R2M)) + +#define IS_DMA2D_CMODE(MODE_ARGB) (((MODE_ARGB) == DMA2D_OUTPUT_ARGB8888) || \ + ((MODE_ARGB) == DMA2D_OUTPUT_RGB888) || \ + ((MODE_ARGB) == DMA2D_OUTPUT_RGB565) || \ + ((MODE_ARGB) == DMA2D_OUTPUT_ARGB1555) || \ + ((MODE_ARGB) == DMA2D_OUTPUT_ARGB4444)) + +#define IS_DMA2D_COLOR(COLOR) ((COLOR) <= DMA2D_COLOR_VALUE) +#define IS_DMA2D_LINE(LINE) ((LINE) <= DMA2D_LINE) +#define IS_DMA2D_PIXEL(PIXEL) ((PIXEL) <= DMA2D_PIXEL) +#define IS_DMA2D_OFFSET(OOFFSET) ((OOFFSET) <= DMA2D_OFFSET) + +#define IS_DMA2D_INPUT_COLOR_MODE(INPUT_CM) (((INPUT_CM) == DMA2D_INPUT_ARGB8888) || \ + ((INPUT_CM) == DMA2D_INPUT_RGB888) || \ + ((INPUT_CM) == DMA2D_INPUT_RGB565) || \ + ((INPUT_CM) == DMA2D_INPUT_ARGB1555) || \ + ((INPUT_CM) == DMA2D_INPUT_ARGB4444) || \ + ((INPUT_CM) == DMA2D_INPUT_L8) || \ + ((INPUT_CM) == DMA2D_INPUT_AL44) || \ + ((INPUT_CM) == DMA2D_INPUT_AL88) || \ + ((INPUT_CM) == DMA2D_INPUT_L4) || \ + ((INPUT_CM) == DMA2D_INPUT_A8) || \ + ((INPUT_CM) == DMA2D_INPUT_A4)) + +#define IS_DMA2D_ALPHA_MODE(AlphaMode) (((AlphaMode) == DMA2D_NO_MODIF_ALPHA) || \ + ((AlphaMode) == DMA2D_REPLACE_ALPHA) || \ + ((AlphaMode) == DMA2D_COMBINE_ALPHA)) + + + + + +#define IS_DMA2D_CLUT_CM(CLUT_CM) (((CLUT_CM) == DMA2D_CCM_ARGB8888) || ((CLUT_CM) == DMA2D_CCM_RGB888)) +#define IS_DMA2D_CLUT_SIZE(CLUT_SIZE) ((CLUT_SIZE) <= DMA2D_CLUT_SIZE) +#define IS_DMA2D_LINEWATERMARK(LineWatermark) ((LineWatermark) <= DMA2D_LINE_WATERMARK_MAX) +#define IS_DMA2D_IT(IT) (((IT) == DMA2D_IT_CTC) || ((IT) == DMA2D_IT_CAE) || \ + ((IT) == DMA2D_IT_TW) || ((IT) == DMA2D_IT_TC) || \ + ((IT) == DMA2D_IT_TE) || ((IT) == DMA2D_IT_CE)) +#define IS_DMA2D_GET_FLAG(FLAG) (((FLAG) == DMA2D_FLAG_CTC) || ((FLAG) == DMA2D_FLAG_CAE) || \ + ((FLAG) == DMA2D_FLAG_TW) || ((FLAG) == DMA2D_FLAG_TC) || \ + ((FLAG) == DMA2D_FLAG_TE) || ((FLAG) == DMA2D_FLAG_CE)) +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (DMA2D) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_DMA2D_H */ diff --git a/libs/hal/stm32f4xx_hal_dma_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_dma_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dma_ex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h new file mode 100644 index 0000000..6da9668 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_dsi.h @@ -0,0 +1,1377 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dsi.h + * @author MCD Application Team + * @brief Header file of DSI 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 STM32F4xx_HAL_DSI_H +#define STM32F4xx_HAL_DSI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined(DSI) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup DSI DSI + * @brief DSI HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup DSI_Exported_Types DSI Exported Types + * @{ + */ +/** + * @brief DSI Init Structure definition + */ +typedef struct +{ + uint32_t AutomaticClockLaneControl; /*!< Automatic clock lane control + This parameter can be any value of @ref DSI_Automatic_Clk_Lane_Control */ + + uint32_t TXEscapeCkdiv; /*!< TX Escape clock division + The values 0 and 1 stop the TX_ESC clock generation */ + + uint32_t NumberOfLanes; /*!< Number of lanes + This parameter can be any value of @ref DSI_Number_Of_Lanes */ + +} DSI_InitTypeDef; + +/** + * @brief DSI PLL Clock structure definition + */ +typedef struct +{ + uint32_t PLLNDIV; /*!< PLL Loop Division Factor + This parameter must be a value between 10 and 125 */ + + uint32_t PLLIDF; /*!< PLL Input Division Factor + This parameter can be any value of @ref DSI_PLL_IDF */ + + uint32_t PLLODF; /*!< PLL Output Division Factor + This parameter can be any value of @ref DSI_PLL_ODF */ + +} DSI_PLLInitTypeDef; + +/** + * @brief DSI Video mode configuration + */ +typedef struct +{ + uint32_t VirtualChannelID; /*!< Virtual channel ID */ + + uint32_t ColorCoding; /*!< Color coding for LTDC interface + This parameter can be any value of @ref DSI_Color_Coding */ + + uint32_t LooselyPacked; /*!< Enable or disable loosely packed stream (needed only when using + 18-bit configuration). + This parameter can be any value of @ref DSI_LooselyPacked */ + + uint32_t Mode; /*!< Video mode type + This parameter can be any value of @ref DSI_Video_Mode_Type */ + + uint32_t PacketSize; /*!< Video packet size */ + + uint32_t NumberOfChunks; /*!< Number of chunks */ + + uint32_t NullPacketSize; /*!< Null packet size */ + + uint32_t HSPolarity; /*!< HSYNC pin polarity + This parameter can be any value of @ref DSI_HSYNC_Polarity */ + + uint32_t VSPolarity; /*!< VSYNC pin polarity + This parameter can be any value of @ref DSI_VSYNC_Active_Polarity */ + + uint32_t DEPolarity; /*!< Data Enable pin polarity + This parameter can be any value of @ref DSI_DATA_ENABLE_Polarity */ + + uint32_t HorizontalSyncActive; /*!< Horizontal synchronism active duration (in lane byte clock cycles) */ + + uint32_t HorizontalBackPorch; /*!< Horizontal back-porch duration (in lane byte clock cycles) */ + + uint32_t HorizontalLine; /*!< Horizontal line duration (in lane byte clock cycles) */ + + uint32_t VerticalSyncActive; /*!< Vertical synchronism active duration */ + + uint32_t VerticalBackPorch; /*!< Vertical back-porch duration */ + + uint32_t VerticalFrontPorch; /*!< Vertical front-porch duration */ + + uint32_t VerticalActive; /*!< Vertical active duration */ + + uint32_t LPCommandEnable; /*!< Low-power command enable + This parameter can be any value of @ref DSI_LP_Command */ + + uint32_t LPLargestPacketSize; /*!< The size, in bytes, of the low power largest packet that + can fit in a line during VSA, VBP and VFP regions */ + + uint32_t LPVACTLargestPacketSize; /*!< The size, in bytes, of the low power largest packet that + can fit in a line during VACT region */ + + uint32_t LPHorizontalFrontPorchEnable; /*!< Low-power horizontal front-porch enable + This parameter can be any value of @ref DSI_LP_HFP */ + + uint32_t LPHorizontalBackPorchEnable; /*!< Low-power horizontal back-porch enable + This parameter can be any value of @ref DSI_LP_HBP */ + + uint32_t LPVerticalActiveEnable; /*!< Low-power vertical active enable + This parameter can be any value of @ref DSI_LP_VACT */ + + uint32_t LPVerticalFrontPorchEnable; /*!< Low-power vertical front-porch enable + This parameter can be any value of @ref DSI_LP_VFP */ + + uint32_t LPVerticalBackPorchEnable; /*!< Low-power vertical back-porch enable + This parameter can be any value of @ref DSI_LP_VBP */ + + uint32_t LPVerticalSyncActiveEnable; /*!< Low-power vertical sync active enable + This parameter can be any value of @ref DSI_LP_VSYNC */ + + uint32_t FrameBTAAcknowledgeEnable; /*!< Frame bus-turn-around acknowledge enable + This parameter can be any value of @ref DSI_FBTA_acknowledge */ + +} DSI_VidCfgTypeDef; + +/** + * @brief DSI Adapted command mode configuration + */ +typedef struct +{ + uint32_t VirtualChannelID; /*!< Virtual channel ID */ + + uint32_t ColorCoding; /*!< Color coding for LTDC interface + This parameter can be any value of @ref DSI_Color_Coding */ + + uint32_t CommandSize; /*!< Maximum allowed size for an LTDC write memory command, measured in + pixels. This parameter can be any value between 0x00 and 0xFFFFU */ + + uint32_t TearingEffectSource; /*!< Tearing effect source + This parameter can be any value of @ref DSI_TearingEffectSource */ + + uint32_t TearingEffectPolarity; /*!< Tearing effect pin polarity + This parameter can be any value of @ref DSI_TearingEffectPolarity */ + + uint32_t HSPolarity; /*!< HSYNC pin polarity + This parameter can be any value of @ref DSI_HSYNC_Polarity */ + + uint32_t VSPolarity; /*!< VSYNC pin polarity + This parameter can be any value of @ref DSI_VSYNC_Active_Polarity */ + + uint32_t DEPolarity; /*!< Data Enable pin polarity + This parameter can be any value of @ref DSI_DATA_ENABLE_Polarity */ + + uint32_t VSyncPol; /*!< VSync edge on which the LTDC is halted + This parameter can be any value of @ref DSI_Vsync_Polarity */ + + uint32_t AutomaticRefresh; /*!< Automatic refresh mode + This parameter can be any value of @ref DSI_AutomaticRefresh */ + + uint32_t TEAcknowledgeRequest; /*!< Tearing Effect Acknowledge Request Enable + This parameter can be any value of @ref DSI_TE_AcknowledgeRequest */ + +} DSI_CmdCfgTypeDef; + +/** + * @brief DSI command transmission mode configuration + */ +typedef struct +{ + uint32_t LPGenShortWriteNoP; /*!< Generic Short Write Zero parameters Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortWriteNoP */ + + uint32_t LPGenShortWriteOneP; /*!< Generic Short Write One parameter Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortWriteOneP */ + + uint32_t LPGenShortWriteTwoP; /*!< Generic Short Write Two parameters Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortWriteTwoP */ + + uint32_t LPGenShortReadNoP; /*!< Generic Short Read Zero parameters Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortReadNoP */ + + uint32_t LPGenShortReadOneP; /*!< Generic Short Read One parameter Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortReadOneP */ + + uint32_t LPGenShortReadTwoP; /*!< Generic Short Read Two parameters Transmission + This parameter can be any value of @ref DSI_LP_LPGenShortReadTwoP */ + + uint32_t LPGenLongWrite; /*!< Generic Long Write Transmission + This parameter can be any value of @ref DSI_LP_LPGenLongWrite */ + + uint32_t LPDcsShortWriteNoP; /*!< DCS Short Write Zero parameters Transmission + This parameter can be any value of @ref DSI_LP_LPDcsShortWriteNoP */ + + uint32_t LPDcsShortWriteOneP; /*!< DCS Short Write One parameter Transmission + This parameter can be any value of @ref DSI_LP_LPDcsShortWriteOneP */ + + uint32_t LPDcsShortReadNoP; /*!< DCS Short Read Zero parameters Transmission + This parameter can be any value of @ref DSI_LP_LPDcsShortReadNoP */ + + uint32_t LPDcsLongWrite; /*!< DCS Long Write Transmission + This parameter can be any value of @ref DSI_LP_LPDcsLongWrite */ + + uint32_t LPMaxReadPacket; /*!< Maximum Read Packet Size Transmission + This parameter can be any value of @ref DSI_LP_LPMaxReadPacket */ + + uint32_t AcknowledgeRequest; /*!< Acknowledge Request Enable + This parameter can be any value of @ref DSI_AcknowledgeRequest */ + +} DSI_LPCmdTypeDef; + +/** + * @brief DSI PHY Timings definition + */ +typedef struct +{ + uint32_t ClockLaneHS2LPTime; /*!< The maximum time that the D-PHY clock lane takes to go from high-speed + to low-power transmission */ + + uint32_t ClockLaneLP2HSTime; /*!< The maximum time that the D-PHY clock lane takes to go from low-power + to high-speed transmission */ + + uint32_t DataLaneHS2LPTime; /*!< The maximum time that the D-PHY data lanes takes to go from high-speed + to low-power transmission */ + + uint32_t DataLaneLP2HSTime; /*!< The maximum time that the D-PHY data lanes takes to go from low-power + to high-speed transmission */ + + uint32_t DataLaneMaxReadTime; /*!< The maximum time required to perform a read command */ + + uint32_t StopWaitTime; /*!< The minimum wait period to request a High-Speed transmission after the + Stop state */ + +} DSI_PHY_TimerTypeDef; + +/** + * @brief DSI HOST Timeouts definition + */ +typedef struct +{ + uint32_t TimeoutCkdiv; /*!< Time-out clock division */ + + uint32_t HighSpeedTransmissionTimeout; /*!< High-speed transmission time-out */ + + uint32_t LowPowerReceptionTimeout; /*!< Low-power reception time-out */ + + uint32_t HighSpeedReadTimeout; /*!< High-speed read time-out */ + + uint32_t LowPowerReadTimeout; /*!< Low-power read time-out */ + + uint32_t HighSpeedWriteTimeout; /*!< High-speed write time-out */ + + uint32_t HighSpeedWritePrespMode; /*!< High-speed write presp mode + This parameter can be any value of @ref DSI_HS_PrespMode */ + + uint32_t LowPowerWriteTimeout; /*!< Low-speed write time-out */ + + uint32_t BTATimeout; /*!< BTA time-out */ + +} DSI_HOST_TimeoutTypeDef; + +/** + * @brief DSI States Structure definition + */ +typedef enum +{ + HAL_DSI_STATE_RESET = 0x00U, + HAL_DSI_STATE_READY = 0x01U, + HAL_DSI_STATE_ERROR = 0x02U, + HAL_DSI_STATE_BUSY = 0x03U, + HAL_DSI_STATE_TIMEOUT = 0x04U +} HAL_DSI_StateTypeDef; + +/** + * @brief DSI Handle Structure definition + */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +typedef struct __DSI_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ +{ + DSI_TypeDef *Instance; /*!< Register base address */ + DSI_InitTypeDef Init; /*!< DSI required parameters */ + HAL_LockTypeDef Lock; /*!< DSI peripheral status */ + __IO HAL_DSI_StateTypeDef State; /*!< DSI communication state */ + __IO uint32_t ErrorCode; /*!< DSI Error code */ + uint32_t ErrorMsk; /*!< DSI Error monitoring mask */ + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + void (* TearingEffectCallback)(struct __DSI_HandleTypeDef *hdsi); /*!< DSI Tearing Effect Callback */ + void (* EndOfRefreshCallback)(struct __DSI_HandleTypeDef *hdsi); /*!< DSI End Of Refresh Callback */ + void (* ErrorCallback)(struct __DSI_HandleTypeDef *hdsi); /*!< DSI Error Callback */ + + void (* MspInitCallback)(struct __DSI_HandleTypeDef *hdsi); /*!< DSI Msp Init callback */ + void (* MspDeInitCallback)(struct __DSI_HandleTypeDef *hdsi); /*!< DSI Msp DeInit callback */ + +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + +} DSI_HandleTypeDef; + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +/** + * @brief HAL DSI Callback ID enumeration definition + */ +typedef enum +{ + HAL_DSI_MSPINIT_CB_ID = 0x00U, /*!< DSI MspInit callback ID */ + HAL_DSI_MSPDEINIT_CB_ID = 0x01U, /*!< DSI MspDeInit callback ID */ + + HAL_DSI_TEARING_EFFECT_CB_ID = 0x02U, /*!< DSI Tearing Effect Callback ID */ + HAL_DSI_ENDOF_REFRESH_CB_ID = 0x03U, /*!< DSI End Of Refresh Callback ID */ + HAL_DSI_ERROR_CB_ID = 0x04U /*!< DSI Error Callback ID */ + +} HAL_DSI_CallbackIDTypeDef; + +/** + * @brief HAL DSI Callback pointer definition + */ +typedef void (*pDSI_CallbackTypeDef)(DSI_HandleTypeDef *hdsi); /*!< pointer to an DSI callback function */ + +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DSI_Exported_Constants DSI Exported Constants + * @{ + */ +/** @defgroup DSI_DCS_Command DSI DCS Command + * @{ + */ +#define DSI_ENTER_IDLE_MODE 0x39U +#define DSI_ENTER_INVERT_MODE 0x21U +#define DSI_ENTER_NORMAL_MODE 0x13U +#define DSI_ENTER_PARTIAL_MODE 0x12U +#define DSI_ENTER_SLEEP_MODE 0x10U +#define DSI_EXIT_IDLE_MODE 0x38U +#define DSI_EXIT_INVERT_MODE 0x20U +#define DSI_EXIT_SLEEP_MODE 0x11U +#define DSI_GET_3D_CONTROL 0x3FU +#define DSI_GET_ADDRESS_MODE 0x0BU +#define DSI_GET_BLUE_CHANNEL 0x08U +#define DSI_GET_DIAGNOSTIC_RESULT 0x0FU +#define DSI_GET_DISPLAY_MODE 0x0DU +#define DSI_GET_GREEN_CHANNEL 0x07U +#define DSI_GET_PIXEL_FORMAT 0x0CU +#define DSI_GET_POWER_MODE 0x0AU +#define DSI_GET_RED_CHANNEL 0x06U +#define DSI_GET_SCANLINE 0x45U +#define DSI_GET_SIGNAL_MODE 0x0EU +#define DSI_NOP 0x00U +#define DSI_READ_DDB_CONTINUE 0xA8U +#define DSI_READ_DDB_START 0xA1U +#define DSI_READ_MEMORY_CONTINUE 0x3EU +#define DSI_READ_MEMORY_START 0x2EU +#define DSI_SET_3D_CONTROL 0x3DU +#define DSI_SET_ADDRESS_MODE 0x36U +#define DSI_SET_COLUMN_ADDRESS 0x2AU +#define DSI_SET_DISPLAY_OFF 0x28U +#define DSI_SET_DISPLAY_ON 0x29U +#define DSI_SET_GAMMA_CURVE 0x26U +#define DSI_SET_PAGE_ADDRESS 0x2BU +#define DSI_SET_PARTIAL_COLUMNS 0x31U +#define DSI_SET_PARTIAL_ROWS 0x30U +#define DSI_SET_PIXEL_FORMAT 0x3AU +#define DSI_SET_SCROLL_AREA 0x33U +#define DSI_SET_SCROLL_START 0x37U +#define DSI_SET_TEAR_OFF 0x34U +#define DSI_SET_TEAR_ON 0x35U +#define DSI_SET_TEAR_SCANLINE 0x44U +#define DSI_SET_VSYNC_TIMING 0x40U +#define DSI_SOFT_RESET 0x01U +#define DSI_WRITE_LUT 0x2DU +#define DSI_WRITE_MEMORY_CONTINUE 0x3CU +#define DSI_WRITE_MEMORY_START 0x2CU +/** + * @} + */ + +/** @defgroup DSI_Video_Mode_Type DSI Video Mode Type + * @{ + */ +#define DSI_VID_MODE_NB_PULSES 0U +#define DSI_VID_MODE_NB_EVENTS 1U +#define DSI_VID_MODE_BURST 2U +/** + * @} + */ + +/** @defgroup DSI_Color_Mode DSI Color Mode + * @{ + */ +#define DSI_COLOR_MODE_FULL 0x00000000U +#define DSI_COLOR_MODE_EIGHT DSI_WCR_COLM +/** + * @} + */ + +/** @defgroup DSI_ShutDown DSI ShutDown + * @{ + */ +#define DSI_DISPLAY_ON 0x00000000U +#define DSI_DISPLAY_OFF DSI_WCR_SHTDN +/** + * @} + */ + +/** @defgroup DSI_LP_Command DSI LP Command + * @{ + */ +#define DSI_LP_COMMAND_DISABLE 0x00000000U +#define DSI_LP_COMMAND_ENABLE DSI_VMCR_LPCE +/** + * @} + */ + +/** @defgroup DSI_LP_HFP DSI LP HFP + * @{ + */ +#define DSI_LP_HFP_DISABLE 0x00000000U +#define DSI_LP_HFP_ENABLE DSI_VMCR_LPHFPE +/** + * @} + */ + +/** @defgroup DSI_LP_HBP DSI LP HBP + * @{ + */ +#define DSI_LP_HBP_DISABLE 0x00000000U +#define DSI_LP_HBP_ENABLE DSI_VMCR_LPHBPE +/** + * @} + */ + +/** @defgroup DSI_LP_VACT DSI LP VACT + * @{ + */ +#define DSI_LP_VACT_DISABLE 0x00000000U +#define DSI_LP_VACT_ENABLE DSI_VMCR_LPVAE +/** + * @} + */ + +/** @defgroup DSI_LP_VFP DSI LP VFP + * @{ + */ +#define DSI_LP_VFP_DISABLE 0x00000000U +#define DSI_LP_VFP_ENABLE DSI_VMCR_LPVFPE +/** + * @} + */ + +/** @defgroup DSI_LP_VBP DSI LP VBP + * @{ + */ +#define DSI_LP_VBP_DISABLE 0x00000000U +#define DSI_LP_VBP_ENABLE DSI_VMCR_LPVBPE +/** + * @} + */ + +/** @defgroup DSI_LP_VSYNC DSI LP VSYNC + * @{ + */ +#define DSI_LP_VSYNC_DISABLE 0x00000000U +#define DSI_LP_VSYNC_ENABLE DSI_VMCR_LPVSAE +/** + * @} + */ + +/** @defgroup DSI_FBTA_acknowledge DSI FBTA Acknowledge + * @{ + */ +#define DSI_FBTAA_DISABLE 0x00000000U +#define DSI_FBTAA_ENABLE DSI_VMCR_FBTAAE +/** + * @} + */ + +/** @defgroup DSI_TearingEffectSource DSI Tearing Effect Source + * @{ + */ +#define DSI_TE_DSILINK 0x00000000U +#define DSI_TE_EXTERNAL DSI_WCFGR_TESRC +/** + * @} + */ + +/** @defgroup DSI_TearingEffectPolarity DSI Tearing Effect Polarity + * @{ + */ +#define DSI_TE_RISING_EDGE 0x00000000U +#define DSI_TE_FALLING_EDGE DSI_WCFGR_TEPOL +/** + * @} + */ + +/** @defgroup DSI_Vsync_Polarity DSI Vsync Polarity + * @{ + */ +#define DSI_VSYNC_FALLING 0x00000000U +#define DSI_VSYNC_RISING DSI_WCFGR_VSPOL +/** + * @} + */ + +/** @defgroup DSI_AutomaticRefresh DSI Automatic Refresh + * @{ + */ +#define DSI_AR_DISABLE 0x00000000U +#define DSI_AR_ENABLE DSI_WCFGR_AR +/** + * @} + */ + +/** @defgroup DSI_TE_AcknowledgeRequest DSI TE Acknowledge Request + * @{ + */ +#define DSI_TE_ACKNOWLEDGE_DISABLE 0x00000000U +#define DSI_TE_ACKNOWLEDGE_ENABLE DSI_CMCR_TEARE +/** + * @} + */ + +/** @defgroup DSI_AcknowledgeRequest DSI Acknowledge Request + * @{ + */ +#define DSI_ACKNOWLEDGE_DISABLE 0x00000000U +#define DSI_ACKNOWLEDGE_ENABLE DSI_CMCR_ARE +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortWriteNoP DSI LP LPGen Short Write NoP + * @{ + */ +#define DSI_LP_GSW0P_DISABLE 0x00000000U +#define DSI_LP_GSW0P_ENABLE DSI_CMCR_GSW0TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortWriteOneP DSI LP LPGen Short Write OneP + * @{ + */ +#define DSI_LP_GSW1P_DISABLE 0x00000000U +#define DSI_LP_GSW1P_ENABLE DSI_CMCR_GSW1TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortWriteTwoP DSI LP LPGen Short Write TwoP + * @{ + */ +#define DSI_LP_GSW2P_DISABLE 0x00000000U +#define DSI_LP_GSW2P_ENABLE DSI_CMCR_GSW2TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortReadNoP DSI LP LPGen Short Read NoP + * @{ + */ +#define DSI_LP_GSR0P_DISABLE 0x00000000U +#define DSI_LP_GSR0P_ENABLE DSI_CMCR_GSR0TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortReadOneP DSI LP LPGen Short Read OneP + * @{ + */ +#define DSI_LP_GSR1P_DISABLE 0x00000000U +#define DSI_LP_GSR1P_ENABLE DSI_CMCR_GSR1TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenShortReadTwoP DSI LP LPGen Short Read TwoP + * @{ + */ +#define DSI_LP_GSR2P_DISABLE 0x00000000U +#define DSI_LP_GSR2P_ENABLE DSI_CMCR_GSR2TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPGenLongWrite DSI LP LPGen LongWrite + * @{ + */ +#define DSI_LP_GLW_DISABLE 0x00000000U +#define DSI_LP_GLW_ENABLE DSI_CMCR_GLWTX +/** + * @} + */ + +/** @defgroup DSI_LP_LPDcsShortWriteNoP DSI LP LPDcs Short Write NoP + * @{ + */ +#define DSI_LP_DSW0P_DISABLE 0x00000000U +#define DSI_LP_DSW0P_ENABLE DSI_CMCR_DSW0TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPDcsShortWriteOneP DSI LP LPDcs Short Write OneP + * @{ + */ +#define DSI_LP_DSW1P_DISABLE 0x00000000U +#define DSI_LP_DSW1P_ENABLE DSI_CMCR_DSW1TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPDcsShortReadNoP DSI LP LPDcs Short Read NoP + * @{ + */ +#define DSI_LP_DSR0P_DISABLE 0x00000000U +#define DSI_LP_DSR0P_ENABLE DSI_CMCR_DSR0TX +/** + * @} + */ + +/** @defgroup DSI_LP_LPDcsLongWrite DSI LP LPDcs Long Write + * @{ + */ +#define DSI_LP_DLW_DISABLE 0x00000000U +#define DSI_LP_DLW_ENABLE DSI_CMCR_DLWTX +/** + * @} + */ + +/** @defgroup DSI_LP_LPMaxReadPacket DSI LP LPMax Read Packet + * @{ + */ +#define DSI_LP_MRDP_DISABLE 0x00000000U +#define DSI_LP_MRDP_ENABLE DSI_CMCR_MRDPS +/** + * @} + */ + +/** @defgroup DSI_HS_PrespMode DSI HS Presp Mode + * @{ + */ +#define DSI_HS_PM_DISABLE 0x00000000U +#define DSI_HS_PM_ENABLE DSI_TCCR3_PM +/** + * @} + */ + + +/** @defgroup DSI_Automatic_Clk_Lane_Control DSI Automatic Clk Lane Control + * @{ + */ +#define DSI_AUTO_CLK_LANE_CTRL_DISABLE 0x00000000U +#define DSI_AUTO_CLK_LANE_CTRL_ENABLE DSI_CLCR_ACR +/** + * @} + */ + +/** @defgroup DSI_Number_Of_Lanes DSI Number Of Lanes + * @{ + */ +#define DSI_ONE_DATA_LANE 0U +#define DSI_TWO_DATA_LANES 1U +/** + * @} + */ + +/** @defgroup DSI_FlowControl DSI Flow Control + * @{ + */ +#define DSI_FLOW_CONTROL_CRC_RX DSI_PCR_CRCRXE +#define DSI_FLOW_CONTROL_ECC_RX DSI_PCR_ECCRXE +#define DSI_FLOW_CONTROL_BTA DSI_PCR_BTAE +#define DSI_FLOW_CONTROL_EOTP_RX DSI_PCR_ETRXE +#define DSI_FLOW_CONTROL_EOTP_TX DSI_PCR_ETTXE +#define DSI_FLOW_CONTROL_ALL (DSI_FLOW_CONTROL_CRC_RX | DSI_FLOW_CONTROL_ECC_RX | \ + DSI_FLOW_CONTROL_BTA | DSI_FLOW_CONTROL_EOTP_RX | \ + DSI_FLOW_CONTROL_EOTP_TX) +/** + * @} + */ + +/** @defgroup DSI_Color_Coding DSI Color Coding + * @{ + */ +#define DSI_RGB565 0x00000000U /*!< The values 0x00000001 and 0x00000002 can also be used for the RGB565 color mode configuration */ +#define DSI_RGB666 0x00000003U /*!< The value 0x00000004 can also be used for the RGB666 color mode configuration */ +#define DSI_RGB888 0x00000005U +/** + * @} + */ + +/** @defgroup DSI_LooselyPacked DSI Loosely Packed + * @{ + */ +#define DSI_LOOSELY_PACKED_ENABLE DSI_LCOLCR_LPE +#define DSI_LOOSELY_PACKED_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup DSI_HSYNC_Polarity DSI HSYNC Polarity + * @{ + */ +#define DSI_HSYNC_ACTIVE_HIGH 0x00000000U +#define DSI_HSYNC_ACTIVE_LOW DSI_LPCR_HSP +/** + * @} + */ + +/** @defgroup DSI_VSYNC_Active_Polarity DSI VSYNC Active Polarity + * @{ + */ +#define DSI_VSYNC_ACTIVE_HIGH 0x00000000U +#define DSI_VSYNC_ACTIVE_LOW DSI_LPCR_VSP +/** + * @} + */ + +/** @defgroup DSI_DATA_ENABLE_Polarity DSI DATA ENABLE Polarity + * @{ + */ +#define DSI_DATA_ENABLE_ACTIVE_HIGH 0x00000000U +#define DSI_DATA_ENABLE_ACTIVE_LOW DSI_LPCR_DEP +/** + * @} + */ + +/** @defgroup DSI_PLL_IDF DSI PLL IDF + * @{ + */ +#define DSI_PLL_IN_DIV1 0x00000001U +#define DSI_PLL_IN_DIV2 0x00000002U +#define DSI_PLL_IN_DIV3 0x00000003U +#define DSI_PLL_IN_DIV4 0x00000004U +#define DSI_PLL_IN_DIV5 0x00000005U +#define DSI_PLL_IN_DIV6 0x00000006U +#define DSI_PLL_IN_DIV7 0x00000007U +/** + * @} + */ + +/** @defgroup DSI_PLL_ODF DSI PLL ODF + * @{ + */ +#define DSI_PLL_OUT_DIV1 0x00000000U +#define DSI_PLL_OUT_DIV2 0x00000001U +#define DSI_PLL_OUT_DIV4 0x00000002U +#define DSI_PLL_OUT_DIV8 0x00000003U +/** + * @} + */ + +/** @defgroup DSI_Flags DSI Flags + * @{ + */ +#define DSI_FLAG_TE DSI_WISR_TEIF +#define DSI_FLAG_ER DSI_WISR_ERIF +#define DSI_FLAG_BUSY DSI_WISR_BUSY +#define DSI_FLAG_PLLLS DSI_WISR_PLLLS +#define DSI_FLAG_PLLL DSI_WISR_PLLLIF +#define DSI_FLAG_PLLU DSI_WISR_PLLUIF +#define DSI_FLAG_RRS DSI_WISR_RRS +#define DSI_FLAG_RR DSI_WISR_RRIF +/** + * @} + */ + +/** @defgroup DSI_Interrupts DSI Interrupts + * @{ + */ +#define DSI_IT_TE DSI_WIER_TEIE +#define DSI_IT_ER DSI_WIER_ERIE +#define DSI_IT_PLLL DSI_WIER_PLLLIE +#define DSI_IT_PLLU DSI_WIER_PLLUIE +#define DSI_IT_RR DSI_WIER_RRIE +/** + * @} + */ + +/** @defgroup DSI_SHORT_WRITE_PKT_Data_Type DSI SHORT WRITE PKT Data Type + * @{ + */ +#define DSI_DCS_SHORT_PKT_WRITE_P0 0x00000005U /*!< DCS short write, no parameters */ +#define DSI_DCS_SHORT_PKT_WRITE_P1 0x00000015U /*!< DCS short write, one parameter */ +#define DSI_GEN_SHORT_PKT_WRITE_P0 0x00000003U /*!< Generic short write, no parameters */ +#define DSI_GEN_SHORT_PKT_WRITE_P1 0x00000013U /*!< Generic short write, one parameter */ +#define DSI_GEN_SHORT_PKT_WRITE_P2 0x00000023U /*!< Generic short write, two parameters */ +/** + * @} + */ + +/** @defgroup DSI_LONG_WRITE_PKT_Data_Type DSI LONG WRITE PKT Data Type + * @{ + */ +#define DSI_DCS_LONG_PKT_WRITE 0x00000039U /*!< DCS long write */ +#define DSI_GEN_LONG_PKT_WRITE 0x00000029U /*!< Generic long write */ +/** + * @} + */ + +/** @defgroup DSI_SHORT_READ_PKT_Data_Type DSI SHORT READ PKT Data Type + * @{ + */ +#define DSI_DCS_SHORT_PKT_READ 0x00000006U /*!< DCS short read */ +#define DSI_GEN_SHORT_PKT_READ_P0 0x00000004U /*!< Generic short read, no parameters */ +#define DSI_GEN_SHORT_PKT_READ_P1 0x00000014U /*!< Generic short read, one parameter */ +#define DSI_GEN_SHORT_PKT_READ_P2 0x00000024U /*!< Generic short read, two parameters */ +/** + * @} + */ + +/** @defgroup DSI_Error_Data_Type DSI Error Data Type + * @{ + */ +#define HAL_DSI_ERROR_NONE 0U +#define HAL_DSI_ERROR_ACK 0x00000001U /*!< Acknowledge errors */ +#define HAL_DSI_ERROR_PHY 0x00000002U /*!< PHY related errors */ +#define HAL_DSI_ERROR_TX 0x00000004U /*!< Transmission error */ +#define HAL_DSI_ERROR_RX 0x00000008U /*!< Reception error */ +#define HAL_DSI_ERROR_ECC 0x00000010U /*!< ECC errors */ +#define HAL_DSI_ERROR_CRC 0x00000020U /*!< CRC error */ +#define HAL_DSI_ERROR_PSE 0x00000040U /*!< Packet Size error */ +#define HAL_DSI_ERROR_EOT 0x00000080U /*!< End Of Transmission error */ +#define HAL_DSI_ERROR_OVF 0x00000100U /*!< FIFO overflow error */ +#define HAL_DSI_ERROR_GEN 0x00000200U /*!< Generic FIFO related errors */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +#define HAL_DSI_ERROR_INVALID_CALLBACK 0x00000400U /*!< DSI Invalid Callback error */ +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup DSI_Lane_Group DSI Lane Group + * @{ + */ +#define DSI_CLOCK_LANE 0x00000000U +#define DSI_DATA_LANES 0x00000001U +/** + * @} + */ + +/** @defgroup DSI_Communication_Delay DSI Communication Delay + * @{ + */ +#define DSI_SLEW_RATE_HSTX 0x00000000U +#define DSI_SLEW_RATE_LPTX 0x00000001U +#define DSI_HS_DELAY 0x00000002U +/** + * @} + */ + +/** @defgroup DSI_CustomLane DSI CustomLane + * @{ + */ +#define DSI_SWAP_LANE_PINS 0x00000000U +#define DSI_INVERT_HS_SIGNAL 0x00000001U +/** + * @} + */ + +/** @defgroup DSI_Lane_Select DSI Lane Select + * @{ + */ +#define DSI_CLK_LANE 0x00000000U +#define DSI_DATA_LANE0 0x00000001U +#define DSI_DATA_LANE1 0x00000002U +/** + * @} + */ + +/** @defgroup DSI_PHY_Timing DSI PHY Timing + * @{ + */ +#define DSI_TCLK_POST 0x00000000U +#define DSI_TLPX_CLK 0x00000001U +#define DSI_THS_EXIT 0x00000002U +#define DSI_TLPX_DATA 0x00000003U +#define DSI_THS_ZERO 0x00000004U +#define DSI_THS_TRAIL 0x00000005U +#define DSI_THS_PREPARE 0x00000006U +#define DSI_TCLK_ZERO 0x00000007U +#define DSI_TCLK_PREPARE 0x00000008U +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup DSI_Exported_Macros DSI Exported Macros + * @{ + */ + +/** + * @brief Reset DSI handle state. + * @param __HANDLE__ DSI handle + * @retval None + */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +#define __HAL_DSI_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_DSI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_DSI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_DSI_STATE_RESET) +#endif /*USE_HAL_DSI_REGISTER_CALLBACKS */ + +/** + * @brief Enables the DSI host. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_ENABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT((__HANDLE__)->Instance->CR, DSI_CR_EN);\ + /* Delay after an DSI Host enabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->CR, DSI_CR_EN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Disables the DSI host. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_DISABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + CLEAR_BIT((__HANDLE__)->Instance->CR, DSI_CR_EN);\ + /* Delay after an DSI Host disabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->CR, DSI_CR_EN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Enables the DSI wrapper. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_WRAPPER_ENABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT((__HANDLE__)->Instance->WCR, DSI_WCR_DSIEN);\ + /* Delay after an DSI warpper enabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WCR, DSI_WCR_DSIEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Disable the DSI wrapper. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_WRAPPER_DISABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + CLEAR_BIT((__HANDLE__)->Instance->WCR, DSI_WCR_DSIEN);\ + /* Delay after an DSI warpper disabling*/ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WCR, DSI_WCR_DSIEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Enables the DSI PLL. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_PLL_ENABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_PLLEN);\ + /* Delay after an DSI PLL enabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_PLLEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Disables the DSI PLL. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_PLL_DISABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + CLEAR_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_PLLEN);\ + /* Delay after an DSI PLL disabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_PLLEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Enables the DSI regulator. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_REG_ENABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + SET_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_REGEN);\ + /* Delay after an DSI regulator enabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_REGEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Disables the DSI regulator. + * @param __HANDLE__ DSI handle + * @retval None. + */ +#define __HAL_DSI_REG_DISABLE(__HANDLE__) do { \ + __IO uint32_t tmpreg = 0x00U; \ + CLEAR_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_REGEN);\ + /* Delay after an DSI regulator disabling */ \ + tmpreg = READ_BIT((__HANDLE__)->Instance->WRPCR, DSI_WRPCR_REGEN);\ + UNUSED(tmpreg); \ + } while(0U) + +/** + * @brief Get the DSI pending flags. + * @param __HANDLE__ DSI handle. + * @param __FLAG__ Get the specified flag. + * This parameter can be any combination of the following values: + * @arg DSI_FLAG_TE : Tearing Effect Interrupt Flag + * @arg DSI_FLAG_ER : End of Refresh Interrupt Flag + * @arg DSI_FLAG_BUSY : Busy Flag + * @arg DSI_FLAG_PLLLS: PLL Lock Status + * @arg DSI_FLAG_PLLL : PLL Lock Interrupt Flag + * @arg DSI_FLAG_PLLU : PLL Unlock Interrupt Flag + * @arg DSI_FLAG_RRS : Regulator Ready Flag + * @arg DSI_FLAG_RR : Regulator Ready Interrupt Flag + * @retval The state of FLAG (SET or RESET). + */ +#define __HAL_DSI_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->WISR & (__FLAG__)) + +/** + * @brief Clears the DSI pending flags. + * @param __HANDLE__ DSI handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg DSI_FLAG_TE : Tearing Effect Interrupt Flag + * @arg DSI_FLAG_ER : End of Refresh Interrupt Flag + * @arg DSI_FLAG_PLLL : PLL Lock Interrupt Flag + * @arg DSI_FLAG_PLLU : PLL Unlock Interrupt Flag + * @arg DSI_FLAG_RR : Regulator Ready Interrupt Flag + * @retval None + */ +#define __HAL_DSI_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->WIFCR = (__FLAG__)) + +/** + * @brief Enables the specified DSI interrupts. + * @param __HANDLE__ DSI handle. + * @param __INTERRUPT__ specifies the DSI interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg DSI_IT_TE : Tearing Effect Interrupt + * @arg DSI_IT_ER : End of Refresh Interrupt + * @arg DSI_IT_PLLL: PLL Lock Interrupt + * @arg DSI_IT_PLLU: PLL Unlock Interrupt + * @arg DSI_IT_RR : Regulator Ready Interrupt + * @retval None + */ +#define __HAL_DSI_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->WIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified DSI interrupts. + * @param __HANDLE__ DSI handle + * @param __INTERRUPT__ specifies the DSI interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg DSI_IT_TE : Tearing Effect Interrupt + * @arg DSI_IT_ER : End of Refresh Interrupt + * @arg DSI_IT_PLLL: PLL Lock Interrupt + * @arg DSI_IT_PLLU: PLL Unlock Interrupt + * @arg DSI_IT_RR : Regulator Ready Interrupt + * @retval None + */ +#define __HAL_DSI_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->WIER &= ~(__INTERRUPT__)) + +/** + * @brief Checks whether the specified DSI interrupt source is enabled or not. + * @param __HANDLE__ DSI handle + * @param __INTERRUPT__ specifies the DSI interrupt source to check. + * This parameter can be one of the following values: + * @arg DSI_IT_TE : Tearing Effect Interrupt + * @arg DSI_IT_ER : End of Refresh Interrupt + * @arg DSI_IT_PLLL: PLL Lock Interrupt + * @arg DSI_IT_PLLU: PLL Unlock Interrupt + * @arg DSI_IT_RR : Regulator Ready Interrupt + * @retval The state of INTERRUPT (SET or RESET). + */ +#define __HAL_DSI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->WIER & (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DSI_Exported_Functions DSI Exported Functions + * @{ + */ +/** @defgroup DSI_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * @{ + */ +HAL_StatusTypeDef HAL_DSI_Init(DSI_HandleTypeDef *hdsi, DSI_PLLInitTypeDef *PLLInit); +HAL_StatusTypeDef HAL_DSI_DeInit(DSI_HandleTypeDef *hdsi); +void HAL_DSI_MspInit(DSI_HandleTypeDef *hdsi); +void HAL_DSI_MspDeInit(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_ConfigErrorMonitor(DSI_HandleTypeDef *hdsi, uint32_t ActiveErrors); +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_DSI_RegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID, + pDSI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup DSI_Group2 IO operation functions + * @brief IO operation functions + * @{ + */ +void HAL_DSI_IRQHandler(DSI_HandleTypeDef *hdsi); +void HAL_DSI_TearingEffectCallback(DSI_HandleTypeDef *hdsi); +void HAL_DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi); +void HAL_DSI_ErrorCallback(DSI_HandleTypeDef *hdsi); +/** + * @} + */ + +/** @defgroup DSI_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_DSI_SetGenericVCID(DSI_HandleTypeDef *hdsi, uint32_t VirtualChannelID); +HAL_StatusTypeDef HAL_DSI_ConfigVideoMode(DSI_HandleTypeDef *hdsi, DSI_VidCfgTypeDef *VidCfg); +HAL_StatusTypeDef HAL_DSI_ConfigAdaptedCommandMode(DSI_HandleTypeDef *hdsi, DSI_CmdCfgTypeDef *CmdCfg); +HAL_StatusTypeDef HAL_DSI_ConfigCommand(DSI_HandleTypeDef *hdsi, DSI_LPCmdTypeDef *LPCmd); +HAL_StatusTypeDef HAL_DSI_ConfigFlowControl(DSI_HandleTypeDef *hdsi, uint32_t FlowControl); +HAL_StatusTypeDef HAL_DSI_ConfigPhyTimer(DSI_HandleTypeDef *hdsi, DSI_PHY_TimerTypeDef *PhyTimers); +HAL_StatusTypeDef HAL_DSI_ConfigHostTimeouts(DSI_HandleTypeDef *hdsi, DSI_HOST_TimeoutTypeDef *HostTimeouts); +HAL_StatusTypeDef HAL_DSI_Start(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_Stop(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_Refresh(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_ColorMode(DSI_HandleTypeDef *hdsi, uint32_t ColorMode); +HAL_StatusTypeDef HAL_DSI_Shutdown(DSI_HandleTypeDef *hdsi, uint32_t Shutdown); +HAL_StatusTypeDef HAL_DSI_ShortWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t Param1, + uint32_t Param2); +HAL_StatusTypeDef HAL_DSI_LongWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t NbParams, + uint32_t Param1, + uint8_t *ParametersTable); +HAL_StatusTypeDef HAL_DSI_Read(DSI_HandleTypeDef *hdsi, + uint32_t ChannelNbr, + uint8_t *Array, + uint32_t Size, + uint32_t Mode, + uint32_t DCSCmd, + uint8_t *ParametersTable); +HAL_StatusTypeDef HAL_DSI_EnterULPMData(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_ExitULPMData(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_EnterULPM(DSI_HandleTypeDef *hdsi); +HAL_StatusTypeDef HAL_DSI_ExitULPM(DSI_HandleTypeDef *hdsi); + +HAL_StatusTypeDef HAL_DSI_PatternGeneratorStart(DSI_HandleTypeDef *hdsi, uint32_t Mode, uint32_t Orientation); +HAL_StatusTypeDef HAL_DSI_PatternGeneratorStop(DSI_HandleTypeDef *hdsi); + +HAL_StatusTypeDef HAL_DSI_SetSlewRateAndDelayTuning(DSI_HandleTypeDef *hdsi, uint32_t CommDelay, uint32_t Lane, + uint32_t Value); +HAL_StatusTypeDef HAL_DSI_SetLowPowerRXFilter(DSI_HandleTypeDef *hdsi, uint32_t Frequency); +HAL_StatusTypeDef HAL_DSI_SetSDD(DSI_HandleTypeDef *hdsi, FunctionalState State); +HAL_StatusTypeDef HAL_DSI_SetLanePinsConfiguration(DSI_HandleTypeDef *hdsi, uint32_t CustomLane, uint32_t Lane, + FunctionalState State); +HAL_StatusTypeDef HAL_DSI_SetPHYTimings(DSI_HandleTypeDef *hdsi, uint32_t Timing, FunctionalState State, + uint32_t Value); +HAL_StatusTypeDef HAL_DSI_ForceTXStopMode(DSI_HandleTypeDef *hdsi, uint32_t Lane, FunctionalState State); +HAL_StatusTypeDef HAL_DSI_ForceRXLowPower(DSI_HandleTypeDef *hdsi, FunctionalState State); +HAL_StatusTypeDef HAL_DSI_ForceDataLanesInRX(DSI_HandleTypeDef *hdsi, FunctionalState State); +HAL_StatusTypeDef HAL_DSI_SetPullDown(DSI_HandleTypeDef *hdsi, FunctionalState State); +HAL_StatusTypeDef HAL_DSI_SetContentionDetectionOff(DSI_HandleTypeDef *hdsi, FunctionalState State); + +/** + * @} + */ + +/** @defgroup DSI_Group4 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * @{ + */ +uint32_t HAL_DSI_GetError(DSI_HandleTypeDef *hdsi); +HAL_DSI_StateTypeDef HAL_DSI_GetState(DSI_HandleTypeDef *hdsi); + +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup DSI_Private_Constants DSI Private Constants + * @{ + */ +#define DSI_MAX_RETURN_PKT_SIZE (0x00000037U) /*!< Maximum return packet configuration */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup DSI_Private_Macros DSI Private Macros + * @{ + */ +#define IS_DSI_PLL_NDIV(NDIV) ((10U <= (NDIV)) && ((NDIV) <= 125U)) +#define IS_DSI_PLL_IDF(IDF) (((IDF) == DSI_PLL_IN_DIV1) || \ + ((IDF) == DSI_PLL_IN_DIV2) || \ + ((IDF) == DSI_PLL_IN_DIV3) || \ + ((IDF) == DSI_PLL_IN_DIV4) || \ + ((IDF) == DSI_PLL_IN_DIV5) || \ + ((IDF) == DSI_PLL_IN_DIV6) || \ + ((IDF) == DSI_PLL_IN_DIV7)) +#define IS_DSI_PLL_ODF(ODF) (((ODF) == DSI_PLL_OUT_DIV1) || \ + ((ODF) == DSI_PLL_OUT_DIV2) || \ + ((ODF) == DSI_PLL_OUT_DIV4) || \ + ((ODF) == DSI_PLL_OUT_DIV8)) +#define IS_DSI_AUTO_CLKLANE_CONTROL(AutoClkLane) (((AutoClkLane) == DSI_AUTO_CLK_LANE_CTRL_DISABLE)\ + || ((AutoClkLane) == DSI_AUTO_CLK_LANE_CTRL_ENABLE)) +#define IS_DSI_NUMBER_OF_LANES(NumberOfLanes) (((NumberOfLanes) == DSI_ONE_DATA_LANE)\ + || ((NumberOfLanes) == DSI_TWO_DATA_LANES)) +#define IS_DSI_FLOW_CONTROL(FlowControl) (((FlowControl) | DSI_FLOW_CONTROL_ALL) == DSI_FLOW_CONTROL_ALL) +#define IS_DSI_COLOR_CODING(ColorCoding) ((ColorCoding) <= 5U) +#define IS_DSI_LOOSELY_PACKED(LooselyPacked) (((LooselyPacked) == DSI_LOOSELY_PACKED_ENABLE)\ + || ((LooselyPacked) == DSI_LOOSELY_PACKED_DISABLE)) +#define IS_DSI_DE_POLARITY(DataEnable) (((DataEnable) == DSI_DATA_ENABLE_ACTIVE_HIGH)\ + || ((DataEnable) == DSI_DATA_ENABLE_ACTIVE_LOW)) +#define IS_DSI_VSYNC_POLARITY(VSYNC) (((VSYNC) == DSI_VSYNC_ACTIVE_HIGH)\ + || ((VSYNC) == DSI_VSYNC_ACTIVE_LOW)) +#define IS_DSI_HSYNC_POLARITY(HSYNC) (((HSYNC) == DSI_HSYNC_ACTIVE_HIGH)\ + || ((HSYNC) == DSI_HSYNC_ACTIVE_LOW)) +#define IS_DSI_VIDEO_MODE_TYPE(VideoModeType) (((VideoModeType) == DSI_VID_MODE_NB_PULSES) || \ + ((VideoModeType) == DSI_VID_MODE_NB_EVENTS) || \ + ((VideoModeType) == DSI_VID_MODE_BURST)) +#define IS_DSI_COLOR_MODE(ColorMode) (((ColorMode) == DSI_COLOR_MODE_FULL)\ + || ((ColorMode) == DSI_COLOR_MODE_EIGHT)) +#define IS_DSI_SHUT_DOWN(ShutDown) (((ShutDown) == DSI_DISPLAY_ON) || ((ShutDown) == DSI_DISPLAY_OFF)) +#define IS_DSI_LP_COMMAND(LPCommand) (((LPCommand) == DSI_LP_COMMAND_DISABLE)\ + || ((LPCommand) == DSI_LP_COMMAND_ENABLE)) +#define IS_DSI_LP_HFP(LPHFP) (((LPHFP) == DSI_LP_HFP_DISABLE) || ((LPHFP) == DSI_LP_HFP_ENABLE)) +#define IS_DSI_LP_HBP(LPHBP) (((LPHBP) == DSI_LP_HBP_DISABLE) || ((LPHBP) == DSI_LP_HBP_ENABLE)) +#define IS_DSI_LP_VACTIVE(LPVActive) (((LPVActive) == DSI_LP_VACT_DISABLE)\ + || ((LPVActive) == DSI_LP_VACT_ENABLE)) +#define IS_DSI_LP_VFP(LPVFP) (((LPVFP) == DSI_LP_VFP_DISABLE) || ((LPVFP) == DSI_LP_VFP_ENABLE)) +#define IS_DSI_LP_VBP(LPVBP) (((LPVBP) == DSI_LP_VBP_DISABLE) || ((LPVBP) == DSI_LP_VBP_ENABLE)) +#define IS_DSI_LP_VSYNC(LPVSYNC) (((LPVSYNC) == DSI_LP_VSYNC_DISABLE)\ + || ((LPVSYNC) == DSI_LP_VSYNC_ENABLE)) +#define IS_DSI_FBTAA(FrameBTAAcknowledge) (((FrameBTAAcknowledge) == DSI_FBTAA_DISABLE)\ + || ((FrameBTAAcknowledge) == DSI_FBTAA_ENABLE)) +#define IS_DSI_TE_SOURCE(TESource) (((TESource) == DSI_TE_DSILINK) || ((TESource) == DSI_TE_EXTERNAL)) +#define IS_DSI_TE_POLARITY(TEPolarity) (((TEPolarity) == DSI_TE_RISING_EDGE)\ + || ((TEPolarity) == DSI_TE_FALLING_EDGE)) +#define IS_DSI_AUTOMATIC_REFRESH(AutomaticRefresh) (((AutomaticRefresh) == DSI_AR_DISABLE)\ + || ((AutomaticRefresh) == DSI_AR_ENABLE)) +#define IS_DSI_VS_POLARITY(VSPolarity) (((VSPolarity) == DSI_VSYNC_FALLING)\ + || ((VSPolarity) == DSI_VSYNC_RISING)) +#define IS_DSI_TE_ACK_REQUEST(TEAcknowledgeRequest) (((TEAcknowledgeRequest) == DSI_TE_ACKNOWLEDGE_DISABLE)\ + || ((TEAcknowledgeRequest) == DSI_TE_ACKNOWLEDGE_ENABLE)) +#define IS_DSI_ACK_REQUEST(AcknowledgeRequest) (((AcknowledgeRequest) == DSI_ACKNOWLEDGE_DISABLE)\ + || ((AcknowledgeRequest) == DSI_ACKNOWLEDGE_ENABLE)) +#define IS_DSI_LP_GSW0P(LP_GSW0P) (((LP_GSW0P) == DSI_LP_GSW0P_DISABLE)\ + || ((LP_GSW0P) == DSI_LP_GSW0P_ENABLE)) +#define IS_DSI_LP_GSW1P(LP_GSW1P) (((LP_GSW1P) == DSI_LP_GSW1P_DISABLE)\ + || ((LP_GSW1P) == DSI_LP_GSW1P_ENABLE)) +#define IS_DSI_LP_GSW2P(LP_GSW2P) (((LP_GSW2P) == DSI_LP_GSW2P_DISABLE)\ + || ((LP_GSW2P) == DSI_LP_GSW2P_ENABLE)) +#define IS_DSI_LP_GSR0P(LP_GSR0P) (((LP_GSR0P) == DSI_LP_GSR0P_DISABLE)\ + || ((LP_GSR0P) == DSI_LP_GSR0P_ENABLE)) +#define IS_DSI_LP_GSR1P(LP_GSR1P) (((LP_GSR1P) == DSI_LP_GSR1P_DISABLE)\ + || ((LP_GSR1P) == DSI_LP_GSR1P_ENABLE)) +#define IS_DSI_LP_GSR2P(LP_GSR2P) (((LP_GSR2P) == DSI_LP_GSR2P_DISABLE)\ + || ((LP_GSR2P) == DSI_LP_GSR2P_ENABLE)) +#define IS_DSI_LP_GLW(LP_GLW) (((LP_GLW) == DSI_LP_GLW_DISABLE)\ + || ((LP_GLW) == DSI_LP_GLW_ENABLE)) +#define IS_DSI_LP_DSW0P(LP_DSW0P) (((LP_DSW0P) == DSI_LP_DSW0P_DISABLE)\ + || ((LP_DSW0P) == DSI_LP_DSW0P_ENABLE)) +#define IS_DSI_LP_DSW1P(LP_DSW1P) (((LP_DSW1P) == DSI_LP_DSW1P_DISABLE)\ + || ((LP_DSW1P) == DSI_LP_DSW1P_ENABLE)) +#define IS_DSI_LP_DSR0P(LP_DSR0P) (((LP_DSR0P) == DSI_LP_DSR0P_DISABLE)\ + || ((LP_DSR0P) == DSI_LP_DSR0P_ENABLE)) +#define IS_DSI_LP_DLW(LP_DLW) (((LP_DLW) == DSI_LP_DLW_DISABLE)\ + || ((LP_DLW) == DSI_LP_DLW_ENABLE)) +#define IS_DSI_LP_MRDP(LP_MRDP) (((LP_MRDP) == DSI_LP_MRDP_DISABLE)\ + || ((LP_MRDP) == DSI_LP_MRDP_ENABLE)) +#define IS_DSI_SHORT_WRITE_PACKET_TYPE(MODE) (((MODE) == DSI_DCS_SHORT_PKT_WRITE_P0) || \ + ((MODE) == DSI_DCS_SHORT_PKT_WRITE_P1) || \ + ((MODE) == DSI_GEN_SHORT_PKT_WRITE_P0) || \ + ((MODE) == DSI_GEN_SHORT_PKT_WRITE_P1) || \ + ((MODE) == DSI_GEN_SHORT_PKT_WRITE_P2)) +#define IS_DSI_LONG_WRITE_PACKET_TYPE(MODE) (((MODE) == DSI_DCS_LONG_PKT_WRITE) || \ + ((MODE) == DSI_GEN_LONG_PKT_WRITE)) +#define IS_DSI_READ_PACKET_TYPE(MODE) (((MODE) == DSI_DCS_SHORT_PKT_READ) || \ + ((MODE) == DSI_GEN_SHORT_PKT_READ_P0) || \ + ((MODE) == DSI_GEN_SHORT_PKT_READ_P1) || \ + ((MODE) == DSI_GEN_SHORT_PKT_READ_P2)) +#define IS_DSI_COMMUNICATION_DELAY(CommDelay) (((CommDelay) == DSI_SLEW_RATE_HSTX) || \ + ((CommDelay) == DSI_SLEW_RATE_LPTX) || \ + ((CommDelay) == DSI_HS_DELAY)) +#define IS_DSI_LANE_GROUP(Lane) (((Lane) == DSI_CLOCK_LANE) || ((Lane) == DSI_DATA_LANES)) +#define IS_DSI_CUSTOM_LANE(CustomLane) (((CustomLane) == DSI_SWAP_LANE_PINS)\ + || ((CustomLane) == DSI_INVERT_HS_SIGNAL)) +#define IS_DSI_LANE(Lane) (((Lane) == DSI_CLOCK_LANE) || \ + ((Lane) == DSI_DATA_LANE0) || ((Lane) == DSI_DATA_LANE1)) +#define IS_DSI_PHY_TIMING(Timing) (((Timing) == DSI_TCLK_POST ) || \ + ((Timing) == DSI_TLPX_CLK ) || \ + ((Timing) == DSI_THS_EXIT ) || \ + ((Timing) == DSI_TLPX_DATA ) || \ + ((Timing) == DSI_THS_ZERO ) || \ + ((Timing) == DSI_THS_TRAIL ) || \ + ((Timing) == DSI_THS_PREPARE ) || \ + ((Timing) == DSI_TCLK_ZERO ) || \ + ((Timing) == DSI_TCLK_PREPARE)) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* DSI */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_DSI_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h new file mode 100644 index 0000000..ba5a09b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_eth.h @@ -0,0 +1,2144 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth.h + * @author MCD Application Team + * @brief Header file of ETH 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 STM32F4xx_HAL_ETH_H +#define STM32F4xx_HAL_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined(ETH) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +#ifndef ETH_TX_DESC_CNT +#define ETH_TX_DESC_CNT 4U +#endif /* ETH_TX_DESC_CNT */ + +#ifndef ETH_RX_DESC_CNT +#define ETH_RX_DESC_CNT 4U +#endif /* ETH_RX_DESC_CNT */ + + +/*********************** Descriptors struct def section ************************/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief ETH DMA Descriptor structure definition + */ +typedef struct +{ + __IO uint32_t DESC0; + __IO uint32_t DESC1; + __IO uint32_t DESC2; + __IO uint32_t DESC3; + __IO uint32_t DESC4; + __IO uint32_t DESC5; + __IO uint32_t DESC6; + __IO uint32_t DESC7; + uint32_t BackupAddr0; /* used to store rx buffer 1 address */ + uint32_t BackupAddr1; /* used to store rx buffer 2 address */ +} ETH_DMADescTypeDef; +/** + * + */ + +/** + * @brief ETH Buffers List structure definition + */ +typedef struct __ETH_BufferTypeDef +{ + uint8_t *buffer; /*gState = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_ETH_STATE_RESET; \ + } while(0) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + &= ~(__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT source enabled or disabled. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The ETH DMA IT Source enabled or disabled + */ +#define __HAL_ETH_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMAIER &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The state of ETH DMA IT (SET or RESET) + */ +#define __HAL_ETH_DMA_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMASR &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMASR = (__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMACSR &\ + ( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Clears the specified ETHERNET DMA flag. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMACSR = ( __FLAG__)) + +/** + * @brief Enables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ +#define __HAL_ETH_MAC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER \ + |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ +#define __HAL_ETH_MAC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER \ + &= ~(__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __INTERRUPT__: specifies the flag to check. @ref ETH_MAC_Interrupts + * @retval The state of ETH MAC IT (SET or RESET). + */ +#define __HAL_ETH_MAC_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MACSR &\ + ( __INTERRUPT__)) == ( __INTERRUPT__)) + +/*!< External interrupt line 19 Connected to the ETH wakeup EXTI Line */ +#define ETH_WAKEUP_EXTI_LINE 0x00080000U + +/** + * @brief Enable the ETH WAKEUP Exti Line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT(__EXTI_LINE__) (EXTI->IMR |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__)) + + +/** + * @brief enable rising edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE(__EXTI_LINE__) (EXTI->FTSR &= ~(__EXTI_LINE__)); \ + (EXTI->RTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR &= ~(__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR |= (__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER |= (__EXTI_LINE__)) + +#define __HAL_ETH_GET_PTP_CONTROL(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->PTPTSCR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +#define __HAL_ETH_SET_PTP_CONTROL(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->PTPTSCR |= (__FLAG__)) +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de initialization functions **********************************/ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth); + +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff); +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode); +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth); + +#ifdef HAL_ETH_USE_PTP +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset); +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth); +#endif /* HAL_ETH_USE_PTP */ + +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout); +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig); + +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue); +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue); + +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxAllocateCallback(uint8_t **buff); +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length); +void HAL_ETH_TxFreeCallback(uint32_t *buff); +void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp); +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions **********************************************/ +/* MAC & DMA Configuration APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, + uint32_t VLANIdentifier); + +/* MAC L2 Packet Filtering APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable); +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(ETH_HandleTypeDef *heth, uint32_t AddrNbr, uint8_t *pMACAddr); + +/* MAC Power Down APIs *****************************************************/ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, ETH_PowerDownConfigTypeDef *pPowerDownConfig); +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count); + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetError(ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetDMAError(ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACError(ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACWakeUpSource(ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_ETH_H */ + + diff --git a/libs/hal/stm32f4xx_hal_exti.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h similarity index 100% rename from libs/hal/stm32f4xx_hal_exti.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_exti.h diff --git a/libs/hal/stm32f4xx_hal_flash.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h similarity index 100% rename from libs/hal/stm32f4xx_hal_flash.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash.h diff --git a/libs/hal/stm32f4xx_hal_flash_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_flash_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ex.h diff --git a/libs/hal/stm32f4xx_hal_flash_ramfunc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h similarity index 100% rename from libs/hal/stm32f4xx_hal_flash_ramfunc.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_flash_ramfunc.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h new file mode 100644 index 0000000..90ab2c6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c.h @@ -0,0 +1,841 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpi2c.h + * @author MCD Application Team + * @brief Header file of FMPI2C 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 STM32F4xx_HAL_FMPI2C_H +#define STM32F4xx_HAL_FMPI2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FMPI2C + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FMPI2C_Exported_Types FMPI2C Exported Types + * @{ + */ + +/** @defgroup FMPI2C_Configuration_Structure_definition FMPI2C Configuration Structure definition + * @brief FMPI2C Configuration Structure definition + * @{ + */ +typedef struct +{ + uint32_t Timing; /*!< Specifies the FMPI2C_TIMINGR_register value. + This parameter calculated by referring to FMPI2C initialization section + in Reference manual */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref FMPI2C_ADDRESSING_MODE */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref FMPI2C_DUAL_ADDRESSING_MODE */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t OwnAddress2Masks; /*!< Specifies the acknowledge mask address second device own address if dual addressing + mode is selected. + This parameter can be a value of @ref FMPI2C_OWN_ADDRESS2_MASKS */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref FMPI2C_GENERAL_CALL_ADDRESSING_MODE */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref FMPI2C_NOSTRETCH_MODE */ + +} FMPI2C_InitTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_state_structure_definition HAL state structure definition + * @brief HAL State structure definition + * @note HAL FMPI2C State value coding follow below described bitmap :\n + * b7-b6 Error information\n + * 00 : No Error\n + * 01 : Abort (Abort user request on going)\n + * 10 : Timeout\n + * 11 : Error\n + * b5 Peripheral initialization status\n + * 0 : Reset (peripheral not initialized)\n + * 1 : Init done (peripheral initialized and ready to use. HAL FMPI2C Init function called)\n + * b4 (not used)\n + * x : Should be set to 0\n + * b3\n + * 0 : Ready or Busy (No Listen mode ongoing)\n + * 1 : Listen (peripheral in Address Listen Mode)\n + * b2 Intrinsic process state\n + * 0 : Ready\n + * 1 : Busy (peripheral busy with some configuration or internal operations)\n + * b1 Rx state\n + * 0 : Ready (no Rx operation ongoing)\n + * 1 : Busy (Rx operation ongoing)\n + * b0 Tx state\n + * 0 : Ready (no Tx operation ongoing)\n + * 1 : Busy (Tx operation ongoing) + * @{ + */ +typedef enum +{ + HAL_FMPI2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_FMPI2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_FMPI2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_FMPI2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_FMPI2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_FMPI2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_FMPI2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_FMPI2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_FMPI2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_FMPI2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_FMPI2C_STATE_ERROR = 0xE0U /*!< Error */ + +} HAL_FMPI2C_StateTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_mode_structure_definition HAL mode structure definition + * @brief HAL Mode structure definition + * @note HAL FMPI2C Mode value coding follow below described bitmap :\n + * b7 (not used)\n + * x : Should be set to 0\n + * b6\n + * 0 : None\n + * 1 : Memory (HAL FMPI2C communication is in Memory Mode)\n + * b5\n + * 0 : None\n + * 1 : Slave (HAL FMPI2C communication is in Slave Mode)\n + * b4\n + * 0 : None\n + * 1 : Master (HAL FMPI2C communication is in Master Mode)\n + * b3-b2-b1-b0 (not used)\n + * xxxx : Should be set to 0000 + * @{ + */ +typedef enum +{ + HAL_FMPI2C_MODE_NONE = 0x00U, /*!< No FMPI2C communication on going */ + HAL_FMPI2C_MODE_MASTER = 0x10U, /*!< FMPI2C communication is in Master Mode */ + HAL_FMPI2C_MODE_SLAVE = 0x20U, /*!< FMPI2C communication is in Slave Mode */ + HAL_FMPI2C_MODE_MEM = 0x40U /*!< FMPI2C communication is in Memory Mode */ + +} HAL_FMPI2C_ModeTypeDef; + +/** + * @} + */ + +/** @defgroup FMPI2C_Error_Code_definition FMPI2C Error Code definition + * @brief FMPI2C Error Code definition + * @{ + */ +#define HAL_FMPI2C_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_FMPI2C_ERROR_BERR (0x00000001U) /*!< BERR error */ +#define HAL_FMPI2C_ERROR_ARLO (0x00000002U) /*!< ARLO error */ +#define HAL_FMPI2C_ERROR_AF (0x00000004U) /*!< ACKF error */ +#define HAL_FMPI2C_ERROR_OVR (0x00000008U) /*!< OVR error */ +#define HAL_FMPI2C_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ +#define HAL_FMPI2C_ERROR_TIMEOUT (0x00000020U) /*!< Timeout error */ +#define HAL_FMPI2C_ERROR_SIZE (0x00000040U) /*!< Size Management error */ +#define HAL_FMPI2C_ERROR_DMA_PARAM (0x00000080U) /*!< DMA Parameter Error */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) +#define HAL_FMPI2C_ERROR_INVALID_CALLBACK (0x00000100U) /*!< Invalid Callback error */ +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ +#define HAL_FMPI2C_ERROR_INVALID_PARAM (0x00000200U) /*!< Invalid Parameters error */ +/** + * @} + */ + +/** @defgroup FMPI2C_handle_Structure_definition FMPI2C handle Structure definition + * @brief FMPI2C handle Structure definition + * @{ + */ +typedef struct __FMPI2C_HandleTypeDef +{ + FMPI2C_TypeDef *Instance; /*!< FMPI2C registers base address */ + + FMPI2C_InitTypeDef Init; /*!< FMPI2C communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to FMPI2C transfer buffer */ + + uint16_t XferSize; /*!< FMPI2C transfer size */ + + __IO uint16_t XferCount; /*!< FMPI2C transfer counter */ + + __IO uint32_t XferOptions; /*!< FMPI2C sequantial transfer options, this parameter can + be a value of @ref FMPI2C_XFEROPTIONS */ + + __IO uint32_t PreviousState; /*!< FMPI2C communication Previous state */ + + HAL_StatusTypeDef(*XferISR)(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, uint32_t ITSources); + /*!< FMPI2C transfer IRQ handler function pointer */ + + DMA_HandleTypeDef *hdmatx; /*!< FMPI2C Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< FMPI2C Rx DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< FMPI2C locking object */ + + __IO HAL_FMPI2C_StateTypeDef State; /*!< FMPI2C communication state */ + + __IO HAL_FMPI2C_ModeTypeDef Mode; /*!< FMPI2C communication mode */ + + __IO uint32_t ErrorCode; /*!< FMPI2C Error code */ + + __IO uint32_t AddrEventCount; /*!< FMPI2C Address Event counter */ + + __IO uint32_t Devaddress; /*!< FMPI2C Target device address */ + + __IO uint32_t Memaddress; /*!< FMPI2C Target memory address */ + +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + void (* MasterTxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Master Tx Transfer completed callback */ + void (* MasterRxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Master Rx Transfer completed callback */ + void (* SlaveTxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Slave Tx Transfer completed callback */ + void (* SlaveRxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Slave Rx Transfer completed callback */ + void (* ListenCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Listen Complete callback */ + void (* MemTxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Memory Tx Transfer completed callback */ + void (* MemRxCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Memory Rx Transfer completed callback */ + void (* ErrorCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Error callback */ + void (* AbortCpltCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Abort callback */ + + void (* AddrCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); + /*!< FMPI2C Slave Address Match callback */ + + void (* MspInitCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Msp Init callback */ + void (* MspDeInitCallback)(struct __FMPI2C_HandleTypeDef *hfmpi2c); + /*!< FMPI2C Msp DeInit callback */ + +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ +} FMPI2C_HandleTypeDef; + +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) +/** + * @brief HAL FMPI2C Callback ID enumeration definition + */ +typedef enum +{ + HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID = 0x00U, /*!< FMPI2C Master Tx Transfer completed callback ID */ + HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID = 0x01U, /*!< FMPI2C Master Rx Transfer completed callback ID */ + HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID = 0x02U, /*!< FMPI2C Slave Tx Transfer completed callback ID */ + HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID = 0x03U, /*!< FMPI2C Slave Rx Transfer completed callback ID */ + HAL_FMPI2C_LISTEN_COMPLETE_CB_ID = 0x04U, /*!< FMPI2C Listen Complete callback ID */ + HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID = 0x05U, /*!< FMPI2C Memory Tx Transfer callback ID */ + HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID = 0x06U, /*!< FMPI2C Memory Rx Transfer completed callback ID */ + HAL_FMPI2C_ERROR_CB_ID = 0x07U, /*!< FMPI2C Error callback ID */ + HAL_FMPI2C_ABORT_CB_ID = 0x08U, /*!< FMPI2C Abort callback ID */ + + HAL_FMPI2C_MSPINIT_CB_ID = 0x09U, /*!< FMPI2C Msp Init callback ID */ + HAL_FMPI2C_MSPDEINIT_CB_ID = 0x0AU /*!< FMPI2C Msp DeInit callback ID */ + +} HAL_FMPI2C_CallbackIDTypeDef; + +/** + * @brief HAL FMPI2C Callback pointer definition + */ +typedef void (*pFMPI2C_CallbackTypeDef)(FMPI2C_HandleTypeDef *hfmpi2c); +/*!< pointer to an FMPI2C callback function */ +typedef void (*pFMPI2C_AddrCallbackTypeDef)(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t TransferDirection, + uint16_t AddrMatchCode); +/*!< pointer to an FMPI2C Address Match callback function */ + +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup FMPI2C_Exported_Constants FMPI2C Exported Constants + * @{ + */ + +/** @defgroup FMPI2C_XFEROPTIONS FMPI2C Sequential Transfer Options + * @{ + */ +#define FMPI2C_FIRST_FRAME ((uint32_t)FMPI2C_SOFTEND_MODE) +#define FMPI2C_FIRST_AND_NEXT_FRAME ((uint32_t)(FMPI2C_RELOAD_MODE | FMPI2C_SOFTEND_MODE)) +#define FMPI2C_NEXT_FRAME ((uint32_t)(FMPI2C_RELOAD_MODE | FMPI2C_SOFTEND_MODE)) +#define FMPI2C_FIRST_AND_LAST_FRAME ((uint32_t)FMPI2C_AUTOEND_MODE) +#define FMPI2C_LAST_FRAME ((uint32_t)FMPI2C_AUTOEND_MODE) +#define FMPI2C_LAST_FRAME_NO_STOP ((uint32_t)FMPI2C_SOFTEND_MODE) + +/* List of XferOptions in usage of : + * 1- Restart condition in all use cases (direction change or not) + */ +#define FMPI2C_OTHER_FRAME (0x000000AAU) +#define FMPI2C_OTHER_AND_LAST_FRAME (0x0000AA00U) +/** + * @} + */ + +/** @defgroup FMPI2C_ADDRESSING_MODE FMPI2C Addressing Mode + * @{ + */ +#define FMPI2C_ADDRESSINGMODE_7BIT (0x00000001U) +#define FMPI2C_ADDRESSINGMODE_10BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup FMPI2C_DUAL_ADDRESSING_MODE FMPI2C Dual Addressing Mode + * @{ + */ +#define FMPI2C_DUALADDRESS_DISABLE (0x00000000U) +#define FMPI2C_DUALADDRESS_ENABLE FMPI2C_OAR2_OA2EN +/** + * @} + */ + +/** @defgroup FMPI2C_OWN_ADDRESS2_MASKS FMPI2C Own Address2 Masks + * @{ + */ +#define FMPI2C_OA2_NOMASK ((uint8_t)0x00U) +#define FMPI2C_OA2_MASK01 ((uint8_t)0x01U) +#define FMPI2C_OA2_MASK02 ((uint8_t)0x02U) +#define FMPI2C_OA2_MASK03 ((uint8_t)0x03U) +#define FMPI2C_OA2_MASK04 ((uint8_t)0x04U) +#define FMPI2C_OA2_MASK05 ((uint8_t)0x05U) +#define FMPI2C_OA2_MASK06 ((uint8_t)0x06U) +#define FMPI2C_OA2_MASK07 ((uint8_t)0x07U) +/** + * @} + */ + +/** @defgroup FMPI2C_GENERAL_CALL_ADDRESSING_MODE FMPI2C General Call Addressing Mode + * @{ + */ +#define FMPI2C_GENERALCALL_DISABLE (0x00000000U) +#define FMPI2C_GENERALCALL_ENABLE FMPI2C_CR1_GCEN +/** + * @} + */ + +/** @defgroup FMPI2C_NOSTRETCH_MODE FMPI2C No-Stretch Mode + * @{ + */ +#define FMPI2C_NOSTRETCH_DISABLE (0x00000000U) +#define FMPI2C_NOSTRETCH_ENABLE FMPI2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup FMPI2C_MEMORY_ADDRESS_SIZE FMPI2C Memory Address Size + * @{ + */ +#define FMPI2C_MEMADD_SIZE_8BIT (0x00000001U) +#define FMPI2C_MEMADD_SIZE_16BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup FMPI2C_XFERDIRECTION FMPI2C Transfer Direction Master Point of View + * @{ + */ +#define FMPI2C_DIRECTION_TRANSMIT (0x00000000U) +#define FMPI2C_DIRECTION_RECEIVE (0x00000001U) +/** + * @} + */ + +/** @defgroup FMPI2C_RELOAD_END_MODE FMPI2C Reload End Mode + * @{ + */ +#define FMPI2C_RELOAD_MODE FMPI2C_CR2_RELOAD +#define FMPI2C_AUTOEND_MODE FMPI2C_CR2_AUTOEND +#define FMPI2C_SOFTEND_MODE (0x00000000U) +/** + * @} + */ + +/** @defgroup FMPI2C_START_STOP_MODE FMPI2C Start or Stop Mode + * @{ + */ +#define FMPI2C_NO_STARTSTOP (0x00000000U) +#define FMPI2C_GENERATE_STOP (uint32_t)(0x80000000U | FMPI2C_CR2_STOP) +#define FMPI2C_GENERATE_START_READ (uint32_t)(0x80000000U | FMPI2C_CR2_START | FMPI2C_CR2_RD_WRN) +#define FMPI2C_GENERATE_START_WRITE (uint32_t)(0x80000000U | FMPI2C_CR2_START) +/** + * @} + */ + +/** @defgroup FMPI2C_Interrupt_configuration_definition FMPI2C Interrupt configuration definition + * @brief FMPI2C Interrupt definition + * Elements values convention: 0xXXXXXXXX + * - XXXXXXXX : Interrupt control mask + * @{ + */ +#define FMPI2C_IT_ERRI FMPI2C_CR1_ERRIE +#define FMPI2C_IT_TCI FMPI2C_CR1_TCIE +#define FMPI2C_IT_STOPI FMPI2C_CR1_STOPIE +#define FMPI2C_IT_NACKI FMPI2C_CR1_NACKIE +#define FMPI2C_IT_ADDRI FMPI2C_CR1_ADDRIE +#define FMPI2C_IT_RXI FMPI2C_CR1_RXIE +#define FMPI2C_IT_TXI FMPI2C_CR1_TXIE +/** + * @} + */ + +/** @defgroup FMPI2C_Flag_definition FMPI2C Flag definition + * @{ + */ +#define FMPI2C_FLAG_TXE FMPI2C_ISR_TXE +#define FMPI2C_FLAG_TXIS FMPI2C_ISR_TXIS +#define FMPI2C_FLAG_RXNE FMPI2C_ISR_RXNE +#define FMPI2C_FLAG_ADDR FMPI2C_ISR_ADDR +#define FMPI2C_FLAG_AF FMPI2C_ISR_NACKF +#define FMPI2C_FLAG_STOPF FMPI2C_ISR_STOPF +#define FMPI2C_FLAG_TC FMPI2C_ISR_TC +#define FMPI2C_FLAG_TCR FMPI2C_ISR_TCR +#define FMPI2C_FLAG_BERR FMPI2C_ISR_BERR +#define FMPI2C_FLAG_ARLO FMPI2C_ISR_ARLO +#define FMPI2C_FLAG_OVR FMPI2C_ISR_OVR +#define FMPI2C_FLAG_PECERR FMPI2C_ISR_PECERR +#define FMPI2C_FLAG_TIMEOUT FMPI2C_ISR_TIMEOUT +#define FMPI2C_FLAG_ALERT FMPI2C_ISR_ALERT +#define FMPI2C_FLAG_BUSY FMPI2C_ISR_BUSY +#define FMPI2C_FLAG_DIR FMPI2C_ISR_DIR +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup FMPI2C_Exported_Macros FMPI2C Exported Macros + * @{ + */ + +/** @brief Reset FMPI2C handle state. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @retval None + */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) +#define __HAL_FMPI2C_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_FMPI2C_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_FMPI2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_FMPI2C_STATE_RESET) +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + +/** @brief Enable the specified FMPI2C interrupt. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_IT_ERRI Errors interrupt enable + * @arg @ref FMPI2C_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPI2C_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPI2C_IT_NACKI NACK received interrupt enable + * @arg @ref FMPI2C_IT_ADDRI Address match interrupt enable + * @arg @ref FMPI2C_IT_RXI RX interrupt enable + * @arg @ref FMPI2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_FMPI2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 |= (__INTERRUPT__)) + +/** @brief Disable the specified FMPI2C interrupt. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_IT_ERRI Errors interrupt enable + * @arg @ref FMPI2C_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPI2C_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPI2C_IT_NACKI NACK received interrupt enable + * @arg @ref FMPI2C_IT_ADDRI Address match interrupt enable + * @arg @ref FMPI2C_IT_RXI RX interrupt enable + * @arg @ref FMPI2C_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_FMPI2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 &= (~(__INTERRUPT__))) + +/** @brief Check whether the specified FMPI2C interrupt source is enabled or not. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @param __INTERRUPT__ specifies the FMPI2C interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_IT_ERRI Errors interrupt enable + * @arg @ref FMPI2C_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPI2C_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPI2C_IT_NACKI NACK received interrupt enable + * @arg @ref FMPI2C_IT_ADDRI Address match interrupt enable + * @arg @ref FMPI2C_IT_RXI RX interrupt enable + * @arg @ref FMPI2C_IT_TXI TX interrupt enable + * + * @retval The new state of __INTERRUPT__ (SET or RESET). + */ +#define __HAL_FMPI2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR1 & \ + (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified FMPI2C flag is set or not. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_FLAG_TXE Transmit data register empty + * @arg @ref FMPI2C_FLAG_TXIS Transmit interrupt status + * @arg @ref FMPI2C_FLAG_RXNE Receive data register not empty + * @arg @ref FMPI2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref FMPI2C_FLAG_AF Acknowledge failure received flag + * @arg @ref FMPI2C_FLAG_STOPF STOP detection flag + * @arg @ref FMPI2C_FLAG_TC Transfer complete (master mode) + * @arg @ref FMPI2C_FLAG_TCR Transfer complete reload + * @arg @ref FMPI2C_FLAG_BERR Bus error + * @arg @ref FMPI2C_FLAG_ARLO Arbitration lost + * @arg @ref FMPI2C_FLAG_OVR Overrun/Underrun + * @arg @ref FMPI2C_FLAG_PECERR PEC error in reception + * @arg @ref FMPI2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref FMPI2C_FLAG_ALERT SMBus alert + * @arg @ref FMPI2C_FLAG_BUSY Bus busy + * @arg @ref FMPI2C_FLAG_DIR Transfer direction (slave mode) + * + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define FMPI2C_FLAG_MASK (0x0001FFFFU) +#define __HAL_FMPI2C_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +/** @brief Clear the FMPI2C pending flags which are cleared by writing 1 in a specific bit. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg @ref FMPI2C_FLAG_TXE Transmit data register empty + * @arg @ref FMPI2C_FLAG_ADDR Address matched (slave mode) + * @arg @ref FMPI2C_FLAG_AF Acknowledge failure received flag + * @arg @ref FMPI2C_FLAG_STOPF STOP detection flag + * @arg @ref FMPI2C_FLAG_BERR Bus error + * @arg @ref FMPI2C_FLAG_ARLO Arbitration lost + * @arg @ref FMPI2C_FLAG_OVR Overrun/Underrun + * @arg @ref FMPI2C_FLAG_PECERR PEC error in reception + * @arg @ref FMPI2C_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref FMPI2C_FLAG_ALERT SMBus alert + * + * @retval None + */ +#define __HAL_FMPI2C_CLEAR_FLAG(__HANDLE__, __FLAG__) (((__FLAG__) == FMPI2C_FLAG_TXE) ? \ + ((__HANDLE__)->Instance->ISR |= (__FLAG__)) : \ + ((__HANDLE__)->Instance->ICR = (__FLAG__))) + +/** @brief Enable the specified FMPI2C peripheral. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @retval None + */ +#define __HAL_FMPI2C_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR1, FMPI2C_CR1_PE)) + +/** @brief Disable the specified FMPI2C peripheral. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @retval None + */ +#define __HAL_FMPI2C_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, FMPI2C_CR1_PE)) + +/** @brief Generate a Non-Acknowledge FMPI2C peripheral in Slave mode. + * @param __HANDLE__ specifies the FMPI2C Handle. + * @retval None + */ +#define __HAL_FMPI2C_GENERATE_NACK(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR2, FMPI2C_CR2_NACK)) +/** + * @} + */ + +/* Include FMPI2C HAL Extended module */ +#include "stm32f4xx_hal_fmpi2c_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FMPI2C_Exported_Functions + * @{ + */ + +/** @addtogroup FMPI2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +/* Initialization and de-initialization functions******************************/ +HAL_StatusTypeDef HAL_FMPI2C_Init(FMPI2C_HandleTypeDef *hfmpi2c); +HAL_StatusTypeDef HAL_FMPI2C_DeInit(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_FMPI2C_RegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID, + pFMPI2C_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_FMPI2C_UnRegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_FMPI2C_RegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, pFMPI2C_AddrCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_FMPI2C_UnRegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup FMPI2C_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* IO operation functions ****************************************************/ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_FMPI2C_IsDeviceReady(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint32_t Trials, + uint32_t Timeout); + +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_EnableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c); +HAL_StatusTypeDef HAL_FMPI2C_DisableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c); +HAL_StatusTypeDef HAL_FMPI2C_Master_Abort_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress); + +/******* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); +/** + * @} + */ + +/** @addtogroup FMPI2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* FMPI2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_FMPI2C_EV_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_ER_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MasterTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MasterRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_SlaveTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_SlaveRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_AddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_FMPI2C_ListenCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MemTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_MemRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_ErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c); +void HAL_FMPI2C_AbortCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c); +/** + * @} + */ + +/** @addtogroup FMPI2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @{ + */ +/* Peripheral State, Mode and Error functions *********************************/ +HAL_FMPI2C_StateTypeDef HAL_FMPI2C_GetState(FMPI2C_HandleTypeDef *hfmpi2c); +HAL_FMPI2C_ModeTypeDef HAL_FMPI2C_GetMode(FMPI2C_HandleTypeDef *hfmpi2c); +uint32_t HAL_FMPI2C_GetError(FMPI2C_HandleTypeDef *hfmpi2c); + +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FMPI2C_Private_Constants FMPI2C Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FMPI2C_Private_Macro FMPI2C Private Macros + * @{ + */ + +#define IS_FMPI2C_ADDRESSING_MODE(MODE) (((MODE) == FMPI2C_ADDRESSINGMODE_7BIT) || \ + ((MODE) == FMPI2C_ADDRESSINGMODE_10BIT)) + +#define IS_FMPI2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == FMPI2C_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == FMPI2C_DUALADDRESS_ENABLE)) + +#define IS_FMPI2C_OWN_ADDRESS2_MASK(MASK) (((MASK) == FMPI2C_OA2_NOMASK) || \ + ((MASK) == FMPI2C_OA2_MASK01) || \ + ((MASK) == FMPI2C_OA2_MASK02) || \ + ((MASK) == FMPI2C_OA2_MASK03) || \ + ((MASK) == FMPI2C_OA2_MASK04) || \ + ((MASK) == FMPI2C_OA2_MASK05) || \ + ((MASK) == FMPI2C_OA2_MASK06) || \ + ((MASK) == FMPI2C_OA2_MASK07)) + +#define IS_FMPI2C_GENERAL_CALL(CALL) (((CALL) == FMPI2C_GENERALCALL_DISABLE) || \ + ((CALL) == FMPI2C_GENERALCALL_ENABLE)) + +#define IS_FMPI2C_NO_STRETCH(STRETCH) (((STRETCH) == FMPI2C_NOSTRETCH_DISABLE) || \ + ((STRETCH) == FMPI2C_NOSTRETCH_ENABLE)) + +#define IS_FMPI2C_MEMADD_SIZE(SIZE) (((SIZE) == FMPI2C_MEMADD_SIZE_8BIT) || \ + ((SIZE) == FMPI2C_MEMADD_SIZE_16BIT)) + +#define IS_TRANSFER_MODE(MODE) (((MODE) == FMPI2C_RELOAD_MODE) || \ + ((MODE) == FMPI2C_AUTOEND_MODE) || \ + ((MODE) == FMPI2C_SOFTEND_MODE)) + +#define IS_TRANSFER_REQUEST(REQUEST) (((REQUEST) == FMPI2C_GENERATE_STOP) || \ + ((REQUEST) == FMPI2C_GENERATE_START_READ) || \ + ((REQUEST) == FMPI2C_GENERATE_START_WRITE) || \ + ((REQUEST) == FMPI2C_NO_STARTSTOP)) + +#define IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == FMPI2C_FIRST_FRAME) || \ + ((REQUEST) == FMPI2C_FIRST_AND_NEXT_FRAME) || \ + ((REQUEST) == FMPI2C_NEXT_FRAME) || \ + ((REQUEST) == FMPI2C_FIRST_AND_LAST_FRAME) || \ + ((REQUEST) == FMPI2C_LAST_FRAME) || \ + ((REQUEST) == FMPI2C_LAST_FRAME_NO_STOP) || \ + IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST)) + +#define IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == FMPI2C_OTHER_FRAME) || \ + ((REQUEST) == FMPI2C_OTHER_AND_LAST_FRAME)) + +#define FMPI2C_RESET_CR2(__HANDLE__) ((__HANDLE__)->Instance->CR2 &= \ + (uint32_t)~((uint32_t)(FMPI2C_CR2_SADD | FMPI2C_CR2_HEAD10R | \ + FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | \ + FMPI2C_CR2_RD_WRN))) + +#define FMPI2C_GET_ADDR_MATCH(__HANDLE__) ((uint16_t)(((__HANDLE__)->Instance->ISR & FMPI2C_ISR_ADDCODE) \ + >> 16U)) +#define FMPI2C_GET_DIR(__HANDLE__) ((uint8_t)(((__HANDLE__)->Instance->ISR & FMPI2C_ISR_DIR) \ + >> 16U)) +#define FMPI2C_GET_STOP_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR2 & FMPI2C_CR2_AUTOEND) +#define FMPI2C_GET_OWN_ADDRESS1(__HANDLE__) ((uint16_t)((__HANDLE__)->Instance->OAR1 & FMPI2C_OAR1_OA1)) +#define FMPI2C_GET_OWN_ADDRESS2(__HANDLE__) ((uint16_t)((__HANDLE__)->Instance->OAR2 & FMPI2C_OAR2_OA2)) + +#define IS_FMPI2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x000003FFU) +#define IS_FMPI2C_OWN_ADDRESS2(ADDRESS2) ((ADDRESS2) <= (uint16_t)0x00FFU) + +#define FMPI2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & \ + (uint16_t)(0xFF00U))) >> 8U))) +#define FMPI2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FFU)))) + +#define FMPI2C_GENERATE_START(__ADDMODE__,__ADDRESS__) (((__ADDMODE__) == FMPI2C_ADDRESSINGMODE_7BIT) ? \ + (uint32_t)((((uint32_t)(__ADDRESS__) & (FMPI2C_CR2_SADD)) | \ + (FMPI2C_CR2_START) | (FMPI2C_CR2_AUTOEND)) & \ + (~FMPI2C_CR2_RD_WRN)) : \ + (uint32_t)((((uint32_t)(__ADDRESS__) & (FMPI2C_CR2_SADD)) | \ + (FMPI2C_CR2_ADD10) | (FMPI2C_CR2_START)) & \ + (~FMPI2C_CR2_RD_WRN))) + +#define FMPI2C_CHECK_FLAG(__ISR__, __FLAG__) ((((__ISR__) & ((__FLAG__) & FMPI2C_FLAG_MASK)) == \ + ((__FLAG__) & FMPI2C_FLAG_MASK)) ? SET : RESET) +#define FMPI2C_CHECK_IT_SOURCE(__CR1__, __IT__) ((((__CR1__) & (__IT__)) == (__IT__)) ? SET : RESET) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup FMPI2C_Private_Functions FMPI2C Private Functions + * @{ + */ +/* Private functions are defined in stm32f4xx_hal_fmpi2c.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_FMPI2C_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h new file mode 100644 index 0000000..8b90f40 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpi2c_ex.h @@ -0,0 +1,150 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpi2c_ex.h + * @author MCD Application Team + * @brief Header file of FMPI2C HAL Extended 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 STM32F4xx_HAL_FMPI2C_EX_H +#define STM32F4xx_HAL_FMPI2C_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FMPI2CEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FMPI2CEx_Exported_Constants FMPI2C Extended Exported Constants + * @{ + */ + +/** @defgroup FMPI2CEx_Analog_Filter FMPI2C Extended Analog Filter + * @{ + */ +#define FMPI2C_ANALOGFILTER_ENABLE 0x00000000U +#define FMPI2C_ANALOGFILTER_DISABLE FMPI2C_CR1_ANFOFF +/** + * @} + */ + +/** @defgroup FMPI2CEx_FastModePlus FMPI2C Extended Fast Mode Plus + * @{ + */ +#define FMPI2C_FASTMODEPLUS_SCL SYSCFG_CFGR_FMPI2C1_SCL /*!< Enable Fast Mode Plus on FMPI2C1 SCL pins */ +#define FMPI2C_FASTMODEPLUS_SDA SYSCFG_CFGR_FMPI2C1_SDA /*!< Enable Fast Mode Plus on FMPI2C1 SDA pins */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup FMPI2CEx_Exported_Macros FMPI2C Extended Exported Macros + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FMPI2CEx_Exported_Functions FMPI2C Extended Exported Functions + * @{ + */ + +/** @addtogroup FMPI2CEx_Exported_Functions_Group1 Filter Mode Functions + * @{ + */ +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_FMPI2CEx_ConfigAnalogFilter(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_FMPI2CEx_ConfigDigitalFilter(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t DigitalFilter); +/** + * @} + */ + +/** @addtogroup FMPI2CEx_Exported_Functions_Group3 Fast Mode Plus Functions + * @{ + */ +void HAL_FMPI2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus); +void HAL_FMPI2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FMPI2CEx_Private_Constants FMPI2C Extended Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FMPI2CEx_Private_Macro FMPI2C Extended Private Macros + * @{ + */ +#define IS_FMPI2C_ANALOG_FILTER(FILTER) (((FILTER) == FMPI2C_ANALOGFILTER_ENABLE) || \ + ((FILTER) == FMPI2C_ANALOGFILTER_DISABLE)) + +#define IS_FMPI2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) + +#define IS_FMPI2C_FASTMODEPLUS(__CONFIG__) ((((__CONFIG__) & (FMPI2C_FASTMODEPLUS_SCL)) == FMPI2C_FASTMODEPLUS_SCL) || \ + (((__CONFIG__) & (FMPI2C_FASTMODEPLUS_SDA)) == FMPI2C_FASTMODEPLUS_SDA)) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup FMPI2CEx_Private_Functions FMPI2C Extended Private Functions + * @{ + */ +/* Private functions are defined in stm32f4xx_hal_fmpi2c_ex.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_FMPI2C_EX_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h new file mode 100644 index 0000000..5086790 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus.h @@ -0,0 +1,793 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpsmbus.h + * @author MCD Application Team + * @brief Header file of FMPSMBUS 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 STM32F4xx_HAL_FMPSMBUS_H +#define STM32F4xx_HAL_FMPSMBUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FMPSMBUS + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup FMPSMBUS_Exported_Types FMPSMBUS Exported Types + * @{ + */ + +/** @defgroup FMPSMBUS_Configuration_Structure_definition FMPSMBUS Configuration Structure definition + * @brief FMPSMBUS Configuration Structure definition + * @{ + */ +typedef struct +{ + uint32_t Timing; /*!< Specifies the FMPSMBUS_TIMINGR_register value. + This parameter calculated by referring to FMPSMBUS initialization section + in Reference manual */ + uint32_t AnalogFilter; /*!< Specifies if Analog Filter is enable or not. + This parameter can be a value of @ref FMPSMBUS_Analog_Filter */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode for master is selected. + This parameter can be a value of @ref FMPSMBUS_addressing_mode */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref FMPSMBUS_dual_addressing_mode */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t OwnAddress2Masks; /*!< Specifies the acknowledge mask address second device own address + if dual addressing mode is selected + This parameter can be a value of @ref FMPSMBUS_own_address2_masks. */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref FMPSMBUS_general_call_addressing_mode. */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref FMPSMBUS_nostretch_mode */ + + uint32_t PacketErrorCheckMode; /*!< Specifies if Packet Error Check mode is selected. + This parameter can be a value of @ref FMPSMBUS_packet_error_check_mode */ + + uint32_t PeripheralMode; /*!< Specifies which mode of Periphal is selected. + This parameter can be a value of @ref FMPSMBUS_peripheral_mode */ + + uint32_t SMBusTimeout; /*!< Specifies the content of the 32 Bits FMPSMBUS_TIMEOUT_register value. + (Enable bits and different timeout values) + This parameter calculated by referring to FMPSMBUS initialization section + in Reference manual */ +} FMPSMBUS_InitTypeDef; +/** + * @} + */ + +/** @defgroup HAL_state_definition HAL state definition + * @brief HAL State definition + * @{ + */ +#define HAL_FMPSMBUS_STATE_RESET (0x00000000U) /*!< FMPSMBUS not yet initialized or disabled */ +#define HAL_FMPSMBUS_STATE_READY (0x00000001U) /*!< FMPSMBUS initialized and ready for use */ +#define HAL_FMPSMBUS_STATE_BUSY (0x00000002U) /*!< FMPSMBUS internal process is ongoing */ +#define HAL_FMPSMBUS_STATE_MASTER_BUSY_TX (0x00000012U) /*!< Master Data Transmission process is ongoing */ +#define HAL_FMPSMBUS_STATE_MASTER_BUSY_RX (0x00000022U) /*!< Master Data Reception process is ongoing */ +#define HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX (0x00000032U) /*!< Slave Data Transmission process is ongoing */ +#define HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX (0x00000042U) /*!< Slave Data Reception process is ongoing */ +#define HAL_FMPSMBUS_STATE_TIMEOUT (0x00000003U) /*!< Timeout state */ +#define HAL_FMPSMBUS_STATE_ERROR (0x00000004U) /*!< Reception process is ongoing */ +#define HAL_FMPSMBUS_STATE_LISTEN (0x00000008U) /*!< Address Listen Mode is ongoing */ +/** + * @} + */ + +/** @defgroup FMPSMBUS_Error_Code_definition FMPSMBUS Error Code definition + * @brief FMPSMBUS Error Code definition + * @{ + */ +#define HAL_FMPSMBUS_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_FMPSMBUS_ERROR_BERR (0x00000001U) /*!< BERR error */ +#define HAL_FMPSMBUS_ERROR_ARLO (0x00000002U) /*!< ARLO error */ +#define HAL_FMPSMBUS_ERROR_ACKF (0x00000004U) /*!< ACKF error */ +#define HAL_FMPSMBUS_ERROR_OVR (0x00000008U) /*!< OVR error */ +#define HAL_FMPSMBUS_ERROR_HALTIMEOUT (0x00000010U) /*!< Timeout error */ +#define HAL_FMPSMBUS_ERROR_BUSTIMEOUT (0x00000020U) /*!< Bus Timeout error */ +#define HAL_FMPSMBUS_ERROR_ALERT (0x00000040U) /*!< Alert error */ +#define HAL_FMPSMBUS_ERROR_PECERR (0x00000080U) /*!< PEC error */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +#define HAL_FMPSMBUS_ERROR_INVALID_CALLBACK (0x00000100U) /*!< Invalid Callback error */ +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ +#define HAL_FMPSMBUS_ERROR_INVALID_PARAM (0x00000200U) /*!< Invalid Parameters error */ +/** + * @} + */ + +/** @defgroup FMPSMBUS_handle_Structure_definition FMPSMBUS handle Structure definition + * @brief FMPSMBUS handle Structure definition + * @{ + */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +typedef struct __FMPSMBUS_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ +{ + FMPI2C_TypeDef *Instance; /*!< FMPSMBUS registers base address */ + + FMPSMBUS_InitTypeDef Init; /*!< FMPSMBUS communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to FMPSMBUS transfer buffer */ + + uint16_t XferSize; /*!< FMPSMBUS transfer size */ + + __IO uint16_t XferCount; /*!< FMPSMBUS transfer counter */ + + __IO uint32_t XferOptions; /*!< FMPSMBUS transfer options */ + + __IO uint32_t PreviousState; /*!< FMPSMBUS communication Previous state */ + + HAL_LockTypeDef Lock; /*!< FMPSMBUS locking object */ + + __IO uint32_t State; /*!< FMPSMBUS communication state */ + + __IO uint32_t ErrorCode; /*!< FMPSMBUS Error code */ + +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + void (* MasterTxCpltCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Master Tx Transfer completed callback */ + void (* MasterRxCpltCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Master Rx Transfer completed callback */ + void (* SlaveTxCpltCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Slave Tx Transfer completed callback */ + void (* SlaveRxCpltCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Slave Rx Transfer completed callback */ + void (* ListenCpltCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Listen Complete callback */ + void (* ErrorCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Error callback */ + + void (* AddrCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode); + /*!< FMPSMBUS Slave Address Match callback */ + + void (* MspInitCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Msp Init callback */ + void (* MspDeInitCallback)(struct __FMPSMBUS_HandleTypeDef *hfmpsmbus); + /*!< FMPSMBUS Msp DeInit callback */ + +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ +} FMPSMBUS_HandleTypeDef; + +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +/** + * @brief HAL FMPSMBUS Callback ID enumeration definition + */ +typedef enum +{ + HAL_FMPSMBUS_MASTER_TX_COMPLETE_CB_ID = 0x00U, /*!< FMPSMBUS Master Tx Transfer completed callback ID */ + HAL_FMPSMBUS_MASTER_RX_COMPLETE_CB_ID = 0x01U, /*!< FMPSMBUS Master Rx Transfer completed callback ID */ + HAL_FMPSMBUS_SLAVE_TX_COMPLETE_CB_ID = 0x02U, /*!< FMPSMBUS Slave Tx Transfer completed callback ID */ + HAL_FMPSMBUS_SLAVE_RX_COMPLETE_CB_ID = 0x03U, /*!< FMPSMBUS Slave Rx Transfer completed callback ID */ + HAL_FMPSMBUS_LISTEN_COMPLETE_CB_ID = 0x04U, /*!< FMPSMBUS Listen Complete callback ID */ + HAL_FMPSMBUS_ERROR_CB_ID = 0x05U, /*!< FMPSMBUS Error callback ID */ + + HAL_FMPSMBUS_MSPINIT_CB_ID = 0x06U, /*!< FMPSMBUS Msp Init callback ID */ + HAL_FMPSMBUS_MSPDEINIT_CB_ID = 0x07U /*!< FMPSMBUS Msp DeInit callback ID */ + +} HAL_FMPSMBUS_CallbackIDTypeDef; + +/** + * @brief HAL FMPSMBUS Callback pointer definition + */ +typedef void (*pFMPSMBUS_CallbackTypeDef)(FMPSMBUS_HandleTypeDef *hfmpsmbus); +/*!< pointer to an FMPSMBUS callback function */ +typedef void (*pFMPSMBUS_AddrCallbackTypeDef)(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t TransferDirection, + uint16_t AddrMatchCode); +/*!< pointer to an FMPSMBUS Address Match callback function */ + +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup FMPSMBUS_Exported_Constants FMPSMBUS Exported Constants + * @{ + */ + +/** @defgroup FMPSMBUS_Analog_Filter FMPSMBUS Analog Filter + * @{ + */ +#define FMPSMBUS_ANALOGFILTER_ENABLE (0x00000000U) +#define FMPSMBUS_ANALOGFILTER_DISABLE FMPI2C_CR1_ANFOFF +/** + * @} + */ + +/** @defgroup FMPSMBUS_addressing_mode FMPSMBUS addressing mode + * @{ + */ +#define FMPSMBUS_ADDRESSINGMODE_7BIT (0x00000001U) +#define FMPSMBUS_ADDRESSINGMODE_10BIT (0x00000002U) +/** + * @} + */ + +/** @defgroup FMPSMBUS_dual_addressing_mode FMPSMBUS dual addressing mode + * @{ + */ + +#define FMPSMBUS_DUALADDRESS_DISABLE (0x00000000U) +#define FMPSMBUS_DUALADDRESS_ENABLE FMPI2C_OAR2_OA2EN +/** + * @} + */ + +/** @defgroup FMPSMBUS_own_address2_masks FMPSMBUS ownaddress2 masks + * @{ + */ + +#define FMPSMBUS_OA2_NOMASK ((uint8_t)0x00U) +#define FMPSMBUS_OA2_MASK01 ((uint8_t)0x01U) +#define FMPSMBUS_OA2_MASK02 ((uint8_t)0x02U) +#define FMPSMBUS_OA2_MASK03 ((uint8_t)0x03U) +#define FMPSMBUS_OA2_MASK04 ((uint8_t)0x04U) +#define FMPSMBUS_OA2_MASK05 ((uint8_t)0x05U) +#define FMPSMBUS_OA2_MASK06 ((uint8_t)0x06U) +#define FMPSMBUS_OA2_MASK07 ((uint8_t)0x07U) +/** + * @} + */ + + +/** @defgroup FMPSMBUS_general_call_addressing_mode FMPSMBUS general call addressing mode + * @{ + */ +#define FMPSMBUS_GENERALCALL_DISABLE (0x00000000U) +#define FMPSMBUS_GENERALCALL_ENABLE FMPI2C_CR1_GCEN +/** + * @} + */ + +/** @defgroup FMPSMBUS_nostretch_mode FMPSMBUS nostretch mode + * @{ + */ +#define FMPSMBUS_NOSTRETCH_DISABLE (0x00000000U) +#define FMPSMBUS_NOSTRETCH_ENABLE FMPI2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup FMPSMBUS_packet_error_check_mode FMPSMBUS packet error check mode + * @{ + */ +#define FMPSMBUS_PEC_DISABLE (0x00000000U) +#define FMPSMBUS_PEC_ENABLE FMPI2C_CR1_PECEN +/** + * @} + */ + +/** @defgroup FMPSMBUS_peripheral_mode FMPSMBUS peripheral mode + * @{ + */ +#define FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_HOST FMPI2C_CR1_SMBHEN +#define FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE (0x00000000U) +#define FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE_ARP FMPI2C_CR1_SMBDEN +/** + * @} + */ + +/** @defgroup FMPSMBUS_ReloadEndMode_definition FMPSMBUS ReloadEndMode definition + * @{ + */ + +#define FMPSMBUS_SOFTEND_MODE (0x00000000U) +#define FMPSMBUS_RELOAD_MODE FMPI2C_CR2_RELOAD +#define FMPSMBUS_AUTOEND_MODE FMPI2C_CR2_AUTOEND +#define FMPSMBUS_SENDPEC_MODE FMPI2C_CR2_PECBYTE +/** + * @} + */ + +/** @defgroup FMPSMBUS_StartStopMode_definition FMPSMBUS StartStopMode definition + * @{ + */ + +#define FMPSMBUS_NO_STARTSTOP (0x00000000U) +#define FMPSMBUS_GENERATE_STOP (uint32_t)(0x80000000U | FMPI2C_CR2_STOP) +#define FMPSMBUS_GENERATE_START_READ (uint32_t)(0x80000000U | FMPI2C_CR2_START | FMPI2C_CR2_RD_WRN) +#define FMPSMBUS_GENERATE_START_WRITE (uint32_t)(0x80000000U | FMPI2C_CR2_START) +/** + * @} + */ + +/** @defgroup FMPSMBUS_XferOptions_definition FMPSMBUS XferOptions definition + * @{ + */ + +/* List of XferOptions in usage of : + * 1- Restart condition when direction change + * 2- No Restart condition in other use cases + */ +#define FMPSMBUS_FIRST_FRAME FMPSMBUS_SOFTEND_MODE +#define FMPSMBUS_NEXT_FRAME ((uint32_t)(FMPSMBUS_RELOAD_MODE | FMPSMBUS_SOFTEND_MODE)) +#define FMPSMBUS_FIRST_AND_LAST_FRAME_NO_PEC FMPSMBUS_AUTOEND_MODE +#define FMPSMBUS_LAST_FRAME_NO_PEC FMPSMBUS_AUTOEND_MODE +#define FMPSMBUS_FIRST_FRAME_WITH_PEC ((uint32_t)(FMPSMBUS_SOFTEND_MODE | FMPSMBUS_SENDPEC_MODE)) +#define FMPSMBUS_FIRST_AND_LAST_FRAME_WITH_PEC ((uint32_t)(FMPSMBUS_AUTOEND_MODE | FMPSMBUS_SENDPEC_MODE)) +#define FMPSMBUS_LAST_FRAME_WITH_PEC ((uint32_t)(FMPSMBUS_AUTOEND_MODE | FMPSMBUS_SENDPEC_MODE)) + +/* List of XferOptions in usage of : + * 1- Restart condition in all use cases (direction change or not) + */ +#define FMPSMBUS_OTHER_FRAME_NO_PEC (0x000000AAU) +#define FMPSMBUS_OTHER_FRAME_WITH_PEC (0x0000AA00U) +#define FMPSMBUS_OTHER_AND_LAST_FRAME_NO_PEC (0x00AA0000U) +#define FMPSMBUS_OTHER_AND_LAST_FRAME_WITH_PEC (0xAA000000U) +/** + * @} + */ + +/** @defgroup FMPSMBUS_Interrupt_configuration_definition FMPSMBUS Interrupt configuration definition + * @brief FMPSMBUS Interrupt definition + * Elements values convention: 0xXXXXXXXX + * - XXXXXXXX : Interrupt control mask + * @{ + */ +#define FMPSMBUS_IT_ERRI FMPI2C_CR1_ERRIE +#define FMPSMBUS_IT_TCI FMPI2C_CR1_TCIE +#define FMPSMBUS_IT_STOPI FMPI2C_CR1_STOPIE +#define FMPSMBUS_IT_NACKI FMPI2C_CR1_NACKIE +#define FMPSMBUS_IT_ADDRI FMPI2C_CR1_ADDRIE +#define FMPSMBUS_IT_RXI FMPI2C_CR1_RXIE +#define FMPSMBUS_IT_TXI FMPI2C_CR1_TXIE +#define FMPSMBUS_IT_TX (FMPSMBUS_IT_ERRI | FMPSMBUS_IT_TCI | FMPSMBUS_IT_STOPI | \ + FMPSMBUS_IT_NACKI | FMPSMBUS_IT_TXI) +#define FMPSMBUS_IT_RX (FMPSMBUS_IT_ERRI | FMPSMBUS_IT_TCI | FMPSMBUS_IT_NACKI | \ + FMPSMBUS_IT_RXI) +#define FMPSMBUS_IT_ALERT (FMPSMBUS_IT_ERRI) +#define FMPSMBUS_IT_ADDR (FMPSMBUS_IT_ADDRI | FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI) +/** + * @} + */ + +/** @defgroup FMPSMBUS_Flag_definition FMPSMBUS Flag definition + * @brief Flag definition + * Elements values convention: 0xXXXXYYYY + * - XXXXXXXX : Flag mask + * @{ + */ + +#define FMPSMBUS_FLAG_TXE FMPI2C_ISR_TXE +#define FMPSMBUS_FLAG_TXIS FMPI2C_ISR_TXIS +#define FMPSMBUS_FLAG_RXNE FMPI2C_ISR_RXNE +#define FMPSMBUS_FLAG_ADDR FMPI2C_ISR_ADDR +#define FMPSMBUS_FLAG_AF FMPI2C_ISR_NACKF +#define FMPSMBUS_FLAG_STOPF FMPI2C_ISR_STOPF +#define FMPSMBUS_FLAG_TC FMPI2C_ISR_TC +#define FMPSMBUS_FLAG_TCR FMPI2C_ISR_TCR +#define FMPSMBUS_FLAG_BERR FMPI2C_ISR_BERR +#define FMPSMBUS_FLAG_ARLO FMPI2C_ISR_ARLO +#define FMPSMBUS_FLAG_OVR FMPI2C_ISR_OVR +#define FMPSMBUS_FLAG_PECERR FMPI2C_ISR_PECERR +#define FMPSMBUS_FLAG_TIMEOUT FMPI2C_ISR_TIMEOUT +#define FMPSMBUS_FLAG_ALERT FMPI2C_ISR_ALERT +#define FMPSMBUS_FLAG_BUSY FMPI2C_ISR_BUSY +#define FMPSMBUS_FLAG_DIR FMPI2C_ISR_DIR +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros ------------------------------------------------------------*/ +/** @defgroup FMPSMBUS_Exported_Macros FMPSMBUS Exported Macros + * @{ + */ + +/** @brief Reset FMPSMBUS handle state. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @retval None + */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +#define __HAL_FMPSMBUS_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_FMPSMBUS_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_FMPSMBUS_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_FMPSMBUS_STATE_RESET) +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + +/** @brief Enable the specified FMPSMBUS interrupts. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref FMPSMBUS_IT_ERRI Errors interrupt enable + * @arg @ref FMPSMBUS_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPSMBUS_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPSMBUS_IT_NACKI NACK received interrupt enable + * @arg @ref FMPSMBUS_IT_ADDRI Address match interrupt enable + * @arg @ref FMPSMBUS_IT_RXI RX interrupt enable + * @arg @ref FMPSMBUS_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_FMPSMBUS_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 |= (__INTERRUPT__)) + +/** @brief Disable the specified FMPSMBUS interrupts. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref FMPSMBUS_IT_ERRI Errors interrupt enable + * @arg @ref FMPSMBUS_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPSMBUS_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPSMBUS_IT_NACKI NACK received interrupt enable + * @arg @ref FMPSMBUS_IT_ADDRI Address match interrupt enable + * @arg @ref FMPSMBUS_IT_RXI RX interrupt enable + * @arg @ref FMPSMBUS_IT_TXI TX interrupt enable + * + * @retval None + */ +#define __HAL_FMPSMBUS_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR1 &= (~(__INTERRUPT__))) + +/** @brief Check whether the specified FMPSMBUS interrupt source is enabled or not. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @param __INTERRUPT__ specifies the FMPSMBUS interrupt source to check. + * This parameter can be one of the following values: + * @arg @ref FMPSMBUS_IT_ERRI Errors interrupt enable + * @arg @ref FMPSMBUS_IT_TCI Transfer complete interrupt enable + * @arg @ref FMPSMBUS_IT_STOPI STOP detection interrupt enable + * @arg @ref FMPSMBUS_IT_NACKI NACK received interrupt enable + * @arg @ref FMPSMBUS_IT_ADDRI Address match interrupt enable + * @arg @ref FMPSMBUS_IT_RXI RX interrupt enable + * @arg @ref FMPSMBUS_IT_TXI TX interrupt enable + * + * @retval The new state of __IT__ (SET or RESET). + */ +#define __HAL_FMPSMBUS_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) \ + ((((__HANDLE__)->Instance->CR1 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified FMPSMBUS flag is set or not. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref FMPSMBUS_FLAG_TXE Transmit data register empty + * @arg @ref FMPSMBUS_FLAG_TXIS Transmit interrupt status + * @arg @ref FMPSMBUS_FLAG_RXNE Receive data register not empty + * @arg @ref FMPSMBUS_FLAG_ADDR Address matched (slave mode) + * @arg @ref FMPSMBUS_FLAG_AF NACK received flag + * @arg @ref FMPSMBUS_FLAG_STOPF STOP detection flag + * @arg @ref FMPSMBUS_FLAG_TC Transfer complete (master mode) + * @arg @ref FMPSMBUS_FLAG_TCR Transfer complete reload + * @arg @ref FMPSMBUS_FLAG_BERR Bus error + * @arg @ref FMPSMBUS_FLAG_ARLO Arbitration lost + * @arg @ref FMPSMBUS_FLAG_OVR Overrun/Underrun + * @arg @ref FMPSMBUS_FLAG_PECERR PEC error in reception + * @arg @ref FMPSMBUS_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref FMPSMBUS_FLAG_ALERT SMBus alert + * @arg @ref FMPSMBUS_FLAG_BUSY Bus busy + * @arg @ref FMPSMBUS_FLAG_DIR Transfer direction (slave mode) + * + * @retval The new state of __FLAG__ (SET or RESET). + */ +#define FMPSMBUS_FLAG_MASK (0x0001FFFFU) +#define __HAL_FMPSMBUS_GET_FLAG(__HANDLE__, __FLAG__) \ + (((((__HANDLE__)->Instance->ISR) & ((__FLAG__) & FMPSMBUS_FLAG_MASK)) == \ + ((__FLAG__) & FMPSMBUS_FLAG_MASK)) ? SET : RESET) + +/** @brief Clear the FMPSMBUS pending flags which are cleared by writing 1 in a specific bit. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg @ref FMPSMBUS_FLAG_TXE Transmit data register empty + * @arg @ref FMPSMBUS_FLAG_ADDR Address matched (slave mode) + * @arg @ref FMPSMBUS_FLAG_AF NACK received flag + * @arg @ref FMPSMBUS_FLAG_STOPF STOP detection flag + * @arg @ref FMPSMBUS_FLAG_BERR Bus error + * @arg @ref FMPSMBUS_FLAG_ARLO Arbitration lost + * @arg @ref FMPSMBUS_FLAG_OVR Overrun/Underrun + * @arg @ref FMPSMBUS_FLAG_PECERR PEC error in reception + * @arg @ref FMPSMBUS_FLAG_TIMEOUT Timeout or Tlow detection flag + * @arg @ref FMPSMBUS_FLAG_ALERT SMBus alert + * + * @retval None + */ +#define __HAL_FMPSMBUS_CLEAR_FLAG(__HANDLE__, __FLAG__) (((__FLAG__) == FMPSMBUS_FLAG_TXE) ? \ + ((__HANDLE__)->Instance->ISR |= (__FLAG__)) : \ + ((__HANDLE__)->Instance->ICR = (__FLAG__))) + +/** @brief Enable the specified FMPSMBUS peripheral. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @retval None + */ +#define __HAL_FMPSMBUS_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR1, FMPI2C_CR1_PE)) + +/** @brief Disable the specified FMPSMBUS peripheral. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @retval None + */ +#define __HAL_FMPSMBUS_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, FMPI2C_CR1_PE)) + +/** @brief Generate a Non-Acknowledge FMPSMBUS peripheral in Slave mode. + * @param __HANDLE__ specifies the FMPSMBUS Handle. + * @retval None + */ +#define __HAL_FMPSMBUS_GENERATE_NACK(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR2, FMPI2C_CR2_NACK)) + +/** + * @} + */ + + +/* Private constants ---------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FMPSMBUS_Private_Macro FMPSMBUS Private Macros + * @{ + */ + +#define IS_FMPSMBUS_ANALOG_FILTER(FILTER) (((FILTER) == FMPSMBUS_ANALOGFILTER_ENABLE) || \ + ((FILTER) == FMPSMBUS_ANALOGFILTER_DISABLE)) + +#define IS_FMPSMBUS_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) + +#define IS_FMPSMBUS_ADDRESSING_MODE(MODE) (((MODE) == FMPSMBUS_ADDRESSINGMODE_7BIT) || \ + ((MODE) == FMPSMBUS_ADDRESSINGMODE_10BIT)) + +#define IS_FMPSMBUS_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == FMPSMBUS_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == FMPSMBUS_DUALADDRESS_ENABLE)) + +#define IS_FMPSMBUS_OWN_ADDRESS2_MASK(MASK) (((MASK) == FMPSMBUS_OA2_NOMASK) || \ + ((MASK) == FMPSMBUS_OA2_MASK01) || \ + ((MASK) == FMPSMBUS_OA2_MASK02) || \ + ((MASK) == FMPSMBUS_OA2_MASK03) || \ + ((MASK) == FMPSMBUS_OA2_MASK04) || \ + ((MASK) == FMPSMBUS_OA2_MASK05) || \ + ((MASK) == FMPSMBUS_OA2_MASK06) || \ + ((MASK) == FMPSMBUS_OA2_MASK07)) + +#define IS_FMPSMBUS_GENERAL_CALL(CALL) (((CALL) == FMPSMBUS_GENERALCALL_DISABLE) || \ + ((CALL) == FMPSMBUS_GENERALCALL_ENABLE)) + +#define IS_FMPSMBUS_NO_STRETCH(STRETCH) (((STRETCH) == FMPSMBUS_NOSTRETCH_DISABLE) || \ + ((STRETCH) == FMPSMBUS_NOSTRETCH_ENABLE)) + +#define IS_FMPSMBUS_PEC(PEC) (((PEC) == FMPSMBUS_PEC_DISABLE) || \ + ((PEC) == FMPSMBUS_PEC_ENABLE)) + +#define IS_FMPSMBUS_PERIPHERAL_MODE(MODE) (((MODE) == FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_HOST) || \ + ((MODE) == FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE) || \ + ((MODE) == FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE_ARP)) + +#define IS_FMPSMBUS_TRANSFER_MODE(MODE) (((MODE) == FMPSMBUS_RELOAD_MODE) || \ + ((MODE) == FMPSMBUS_AUTOEND_MODE) || \ + ((MODE) == FMPSMBUS_SOFTEND_MODE) || \ + ((MODE) == FMPSMBUS_SENDPEC_MODE) || \ + ((MODE) == (FMPSMBUS_RELOAD_MODE | FMPSMBUS_SENDPEC_MODE)) || \ + ((MODE) == (FMPSMBUS_AUTOEND_MODE | FMPSMBUS_SENDPEC_MODE)) || \ + ((MODE) == (FMPSMBUS_AUTOEND_MODE | FMPSMBUS_RELOAD_MODE)) || \ + ((MODE) == (FMPSMBUS_AUTOEND_MODE | FMPSMBUS_SENDPEC_MODE | \ + FMPSMBUS_RELOAD_MODE ))) + + +#define IS_FMPSMBUS_TRANSFER_REQUEST(REQUEST) (((REQUEST) == FMPSMBUS_GENERATE_STOP) || \ + ((REQUEST) == FMPSMBUS_GENERATE_START_READ) || \ + ((REQUEST) == FMPSMBUS_GENERATE_START_WRITE) || \ + ((REQUEST) == FMPSMBUS_NO_STARTSTOP)) + + +#define IS_FMPSMBUS_TRANSFER_OPTIONS_REQUEST(REQUEST) (IS_FMPSMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST) || \ + ((REQUEST) == FMPSMBUS_FIRST_FRAME) || \ + ((REQUEST) == FMPSMBUS_NEXT_FRAME) || \ + ((REQUEST) == FMPSMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || \ + ((REQUEST) == FMPSMBUS_LAST_FRAME_NO_PEC) || \ + ((REQUEST) == FMPSMBUS_FIRST_FRAME_WITH_PEC) || \ + ((REQUEST) == FMPSMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || \ + ((REQUEST) == FMPSMBUS_LAST_FRAME_WITH_PEC)) + +#define IS_FMPSMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == FMPSMBUS_OTHER_FRAME_NO_PEC) || \ + ((REQUEST) == FMPSMBUS_OTHER_AND_LAST_FRAME_NO_PEC) || \ + ((REQUEST) == FMPSMBUS_OTHER_FRAME_WITH_PEC) || \ + ((REQUEST) == FMPSMBUS_OTHER_AND_LAST_FRAME_WITH_PEC)) + +#define FMPSMBUS_RESET_CR1(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= \ + (uint32_t)~((uint32_t)(FMPI2C_CR1_SMBHEN | FMPI2C_CR1_SMBDEN | \ + FMPI2C_CR1_PECEN))) +#define FMPSMBUS_RESET_CR2(__HANDLE__) ((__HANDLE__)->Instance->CR2 &= \ + (uint32_t)~((uint32_t)(FMPI2C_CR2_SADD | FMPI2C_CR2_HEAD10R | \ + FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | \ + FMPI2C_CR2_RD_WRN))) + +#define FMPSMBUS_GENERATE_START(__ADDMODE__,__ADDRESS__) (((__ADDMODE__) == FMPSMBUS_ADDRESSINGMODE_7BIT) ? \ + (uint32_t)((((uint32_t)(__ADDRESS__) & (FMPI2C_CR2_SADD)) | \ + (FMPI2C_CR2_START) | (FMPI2C_CR2_AUTOEND)) & \ + (~FMPI2C_CR2_RD_WRN)) : \ + (uint32_t)((((uint32_t)(__ADDRESS__) & \ + (FMPI2C_CR2_SADD)) | (FMPI2C_CR2_ADD10) | \ + (FMPI2C_CR2_START)) & (~FMPI2C_CR2_RD_WRN))) + +#define FMPSMBUS_GET_ADDR_MATCH(__HANDLE__) (((__HANDLE__)->Instance->ISR & FMPI2C_ISR_ADDCODE) >> 17U) +#define FMPSMBUS_GET_DIR(__HANDLE__) (((__HANDLE__)->Instance->ISR & FMPI2C_ISR_DIR) >> 16U) +#define FMPSMBUS_GET_STOP_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR2 & FMPI2C_CR2_AUTOEND) +#define FMPSMBUS_GET_PEC_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR2 & FMPI2C_CR2_PECBYTE) +#define FMPSMBUS_GET_ALERT_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR1 & FMPI2C_CR1_ALERTEN) + +#define FMPSMBUS_CHECK_FLAG(__ISR__, __FLAG__) ((((__ISR__) & ((__FLAG__) & FMPSMBUS_FLAG_MASK)) == \ + ((__FLAG__) & FMPSMBUS_FLAG_MASK)) ? SET : RESET) +#define FMPSMBUS_CHECK_IT_SOURCE(__CR1__, __IT__) ((((__CR1__) & (__IT__)) == (__IT__)) ? SET : RESET) + +#define IS_FMPSMBUS_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x000003FFU) +#define IS_FMPSMBUS_OWN_ADDRESS2(ADDRESS2) ((ADDRESS2) <= (uint16_t)0x00FFU) + +/** + * @} + */ + +/* Include FMPSMBUS HAL Extended module */ +#include "stm32f4xx_hal_fmpsmbus_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FMPSMBUS_Exported_Functions FMPSMBUS Exported Functions + * @{ + */ + +/** @addtogroup FMPSMBUS_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_FMPSMBUS_Init(FMPSMBUS_HandleTypeDef *hfmpsmbus); +HAL_StatusTypeDef HAL_FMPSMBUS_DeInit(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_MspInit(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_MspDeInit(FMPSMBUS_HandleTypeDef *hfmpsmbus); +HAL_StatusTypeDef HAL_FMPSMBUS_ConfigAnalogFilter(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_FMPSMBUS_ConfigDigitalFilter(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t DigitalFilter); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_FMPSMBUS_RegisterCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + HAL_FMPSMBUS_CallbackIDTypeDef CallbackID, + pFMPSMBUS_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_FMPSMBUS_UnRegisterCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + HAL_FMPSMBUS_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_FMPSMBUS_RegisterAddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + pFMPSMBUS_AddrCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_FMPSMBUS_UnRegisterAddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup FMPSMBUS_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +/** @addtogroup Blocking_mode_Polling Blocking mode Polling + * @{ + */ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_FMPSMBUS_IsDeviceReady(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, uint32_t Trials, + uint32_t Timeout); +/** + * @} + */ + +/** @addtogroup Non-Blocking_mode_Interrupt Non-Blocking mode Interrupt + * @{ + */ +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Transmit_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, + uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Receive_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, + uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Abort_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress); +HAL_StatusTypeDef HAL_FMPSMBUS_Slave_Transmit_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); +HAL_StatusTypeDef HAL_FMPSMBUS_Slave_Receive_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t *pData, uint16_t Size, + uint32_t XferOptions); + +HAL_StatusTypeDef HAL_FMPSMBUS_EnableAlert_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus); +HAL_StatusTypeDef HAL_FMPSMBUS_DisableAlert_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus); +HAL_StatusTypeDef HAL_FMPSMBUS_EnableListen_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus); +HAL_StatusTypeDef HAL_FMPSMBUS_DisableListen_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus); +/** + * @} + */ + +/** @addtogroup FMPSMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* FMPSMBUS IRQHandler and Callbacks used in non blocking modes (Interrupt) */ +void HAL_FMPSMBUS_EV_IRQHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_ER_IRQHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_MasterTxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_MasterRxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_SlaveTxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_SlaveRxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_AddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_FMPSMBUS_ListenCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); +void HAL_FMPSMBUS_ErrorCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus); + +/** + * @} + */ + +/** @addtogroup FMPSMBUS_Exported_Functions_Group3 Peripheral State and Errors functions + * @{ + */ + +/* Peripheral State and Errors functions **************************************************/ +uint32_t HAL_FMPSMBUS_GetState(FMPSMBUS_HandleTypeDef *hfmpsmbus); +uint32_t HAL_FMPSMBUS_GetError(FMPSMBUS_HandleTypeDef *hfmpsmbus); + +/** + * @} + */ + +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup FMPSMBUS_Private_Functions FMPSMBUS Private Functions + * @{ + */ +/* Private functions are defined in stm32f4xx_hal_fmpsmbus.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_FMPSMBUS_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus_ex.h new file mode 100644 index 0000000..001dc54 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_fmpsmbus_ex.h @@ -0,0 +1,136 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpsmbus_ex.h + * @author MCD Application Team + * @brief Header file of FMPSMBUS HAL Extended 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 STM32F4xx_HAL_FMPSMBUS_EX_H +#define STM32F4xx_HAL_FMPSMBUS_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FMPSMBUSEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FMPSMBUSEx_Exported_Constants FMPSMBUS Extended Exported Constants + * @{ + */ + +/** @defgroup FMPSMBUSEx_FastModePlus FMPSMBUS Extended Fast Mode Plus + * @{ + */ +#define FMPSMBUS_FASTMODEPLUS_SCL SYSCFG_CFGR_FMPI2C1_SCL /*!< Enable Fast Mode Plus on FMPI2C1 SCL pins */ +#define FMPSMBUS_FASTMODEPLUS_SDA SYSCFG_CFGR_FMPI2C1_SDA /*!< Enable Fast Mode Plus on FMPI2C1 SDA pins */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup FMPSMBUSEx_Exported_Macros FMPSMBUS Extended Exported Macros + * @{ + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FMPSMBUSEx_Exported_Functions FMPSMBUS Extended Exported Functions + * @{ + */ + +/** @addtogroup FMPSMBUSEx_Exported_Functions_Group2 WakeUp Mode Functions + * @{ + */ +/* Peripheral Control functions ************************************************/ +/** + * @} + */ + +/** @addtogroup FMPSMBUSEx_Exported_Functions_Group3 Fast Mode Plus Functions + * @{ + */ +void HAL_FMPSMBUSEx_EnableFastModePlus(uint32_t ConfigFastModePlus); +void HAL_FMPSMBUSEx_DisableFastModePlus(uint32_t ConfigFastModePlus); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FMPSMBUSEx_Private_Constants FMPSMBUS Extended Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup FMPSMBUSEx_Private_Macro FMPSMBUS Extended Private Macros + * @{ + */ +#define IS_FMPSMBUS_FASTMODEPLUS(__CONFIG__) ((((__CONFIG__) & (FMPSMBUS_FASTMODEPLUS_SCL)) == \ + FMPSMBUS_FASTMODEPLUS_SCL) || \ + (((__CONFIG__) & (FMPSMBUS_FASTMODEPLUS_SDA)) == \ + FMPSMBUS_FASTMODEPLUS_SDA)) +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup FMPSMBUSEx_Private_Functions FMPSMBUS Extended Private Functions + * @{ + */ +/* Private functions are defined in stm32f4xx_hal_fmpsmbus_ex.c file */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_FMPSMBUS_EX_H */ diff --git a/libs/hal/stm32f4xx_hal_gpio.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h similarity index 100% rename from libs/hal/stm32f4xx_hal_gpio.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio.h diff --git a/libs/hal/stm32f4xx_hal_gpio_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_gpio_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_gpio_ex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h new file mode 100644 index 0000000..9a93fbb --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash.h @@ -0,0 +1,634 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hash.h + * @author MCD Application Team + * @brief Header file of HASH 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 STM32F4xx_HAL_HASH_H +#define STM32F4xx_HAL_HASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (HASH) +/** @addtogroup HASH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup HASH_Exported_Types HASH Exported Types + * @{ + */ + +/** + * @brief HASH Configuration Structure definition + */ +typedef struct +{ + uint32_t DataType; /*!< 32-bit data, 16-bit data, 8-bit data or 1-bit data. + This parameter can be a value of @ref HASH_Data_Type. */ + + uint32_t KeySize; /*!< The key size is used only in HMAC operation. */ + + uint8_t *pKey; /*!< The key is used only in HMAC operation. */ + +} HASH_InitTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_HASH_STATE_RESET = 0x00U, /*!< Peripheral is not initialized */ + HAL_HASH_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_HASH_STATE_BUSY = 0x02U, /*!< Processing (hashing) is ongoing */ + HAL_HASH_STATE_TIMEOUT = 0x06U, /*!< Timeout state */ + HAL_HASH_STATE_ERROR = 0x07U, /*!< Error state */ + HAL_HASH_STATE_SUSPENDED = 0x08U /*!< Suspended state */ +} HAL_HASH_StateTypeDef; + +/** + * @brief HAL phase structures definition + */ +typedef enum +{ + HAL_HASH_PHASE_READY = 0x01U, /*!< HASH peripheral is ready to start */ + HAL_HASH_PHASE_PROCESS = 0x02U, /*!< HASH peripheral is in HASH processing phase */ + HAL_HASH_PHASE_HMAC_STEP_1 = 0x03U, /*!< HASH peripheral is in HMAC step 1 processing phase + (step 1 consists in entering the inner hash function key) */ + HAL_HASH_PHASE_HMAC_STEP_2 = 0x04U, /*!< HASH peripheral is in HMAC step 2 processing phase + (step 2 consists in entering the message text) */ + HAL_HASH_PHASE_HMAC_STEP_3 = 0x05U /*!< HASH peripheral is in HMAC step 3 processing phase + (step 3 consists in entering the outer hash function key) */ +} HAL_HASH_PhaseTypeDef; + +/** + * @brief HAL HASH mode suspend definitions + */ +typedef enum +{ + HAL_HASH_SUSPEND_NONE = 0x00U, /*!< HASH peripheral suspension not requested */ + HAL_HASH_SUSPEND = 0x01U /*!< HASH peripheral suspension is requested */ +} HAL_HASH_SuspendTypeDef; + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1U) +/** + * @brief HAL HASH common Callback ID enumeration definition + */ +typedef enum +{ + HAL_HASH_MSPINIT_CB_ID = 0x00U, /*!< HASH MspInit callback ID */ + HAL_HASH_MSPDEINIT_CB_ID = 0x01U, /*!< HASH MspDeInit callback ID */ + HAL_HASH_INPUTCPLT_CB_ID = 0x02U, /*!< HASH input completion callback ID */ + HAL_HASH_DGSTCPLT_CB_ID = 0x03U, /*!< HASH digest computation completion callback ID */ + HAL_HASH_ERROR_CB_ID = 0x04U, /*!< HASH error callback ID */ +} HAL_HASH_CallbackIDTypeDef; +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + +/** + * @brief HASH Handle Structure definition + */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) +typedef struct __HASH_HandleTypeDef +#else +typedef struct +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ +{ + HASH_InitTypeDef Init; /*!< HASH required parameters */ + + uint8_t *pHashInBuffPtr; /*!< Pointer to input buffer */ + + uint8_t *pHashOutBuffPtr; /*!< Pointer to output buffer (digest) */ + + uint8_t *pHashKeyBuffPtr; /*!< Pointer to key buffer (HMAC only) */ + + uint8_t *pHashMsgBuffPtr; /*!< Pointer to message buffer (HMAC only) */ + + uint32_t HashBuffSize; /*!< Size of buffer to be processed */ + + __IO uint32_t HashInCount; /*!< Counter of inputted data */ + + __IO uint32_t HashITCounter; /*!< Counter of issued interrupts */ + + __IO uint32_t HashKeyCount; /*!< Counter for Key inputted data (HMAC only) */ + + HAL_StatusTypeDef Status; /*!< HASH peripheral status */ + + HAL_HASH_PhaseTypeDef Phase; /*!< HASH peripheral phase */ + + DMA_HandleTypeDef *hdmain; /*!< HASH In DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_HASH_StateTypeDef State; /*!< HASH peripheral state */ + + HAL_HASH_SuspendTypeDef SuspendRequest; /*!< HASH peripheral suspension request flag */ + + FlagStatus DigestCalculationDisable; /*!< Digest calculation phase skip (MDMAT bit control) for multi-buffers DMA-based HMAC computation */ + + __IO uint32_t NbWordsAlreadyPushed; /*!< Numbers of words already pushed in FIFO before inputting new block */ + + __IO uint32_t ErrorCode; /*!< HASH Error code */ + + __IO uint32_t Accumulation; /*!< HASH multi buffers accumulation flag */ + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + void (* InCpltCallback)(struct __HASH_HandleTypeDef *hhash); /*!< HASH input completion callback */ + + void (* DgstCpltCallback)(struct __HASH_HandleTypeDef *hhash); /*!< HASH digest computation completion callback */ + + void (* ErrorCallback)(struct __HASH_HandleTypeDef *hhash); /*!< HASH error callback */ + + void (* MspInitCallback)(struct __HASH_HandleTypeDef *hhash); /*!< HASH Msp Init callback */ + + void (* MspDeInitCallback)(struct __HASH_HandleTypeDef *hhash); /*!< HASH Msp DeInit callback */ + +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ +} HASH_HandleTypeDef; + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1U) +/** + * @brief HAL HASH Callback pointer definition + */ +typedef void (*pHASH_CallbackTypeDef)(HASH_HandleTypeDef *hhash); /*!< pointer to a HASH common callback functions */ +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup HASH_Exported_Constants HASH Exported Constants + * @{ + */ + +/** @defgroup HASH_Algo_Selection HASH algorithm selection + * @{ + */ +#define HASH_ALGOSELECTION_SHA1 0x00000000U /*!< HASH function is SHA1 */ +#define HASH_ALGOSELECTION_MD5 HASH_CR_ALGO_0 /*!< HASH function is MD5 */ +#define HASH_ALGOSELECTION_SHA224 HASH_CR_ALGO_1 /*!< HASH function is SHA224 */ +#define HASH_ALGOSELECTION_SHA256 HASH_CR_ALGO /*!< HASH function is SHA256 */ +/** + * @} + */ + +/** @defgroup HASH_Algorithm_Mode HASH algorithm mode + * @{ + */ +#define HASH_ALGOMODE_HASH 0x00000000U /*!< Algorithm is HASH */ +#define HASH_ALGOMODE_HMAC HASH_CR_MODE /*!< Algorithm is HMAC */ +/** + * @} + */ + +/** @defgroup HASH_Data_Type HASH input data type + * @{ + */ +#define HASH_DATATYPE_32B 0x00000000U /*!< 32-bit data. No swapping */ +#define HASH_DATATYPE_16B HASH_CR_DATATYPE_0 /*!< 16-bit data. Each half word is swapped */ +#define HASH_DATATYPE_8B HASH_CR_DATATYPE_1 /*!< 8-bit data. All bytes are swapped */ +#define HASH_DATATYPE_1B HASH_CR_DATATYPE /*!< 1-bit data. In the word all bits are swapped */ +/** + * @} + */ + +/** @defgroup HASH_HMAC_Long_key_only_for_HMAC_mode HMAC key length type + * @{ + */ +#define HASH_HMAC_KEYTYPE_SHORTKEY 0x00000000U /*!< HMAC Key size is <= 64 bytes */ +#define HASH_HMAC_KEYTYPE_LONGKEY HASH_CR_LKEY /*!< HMAC Key size is > 64 bytes */ +/** + * @} + */ + +/** @defgroup HASH_flags_definition HASH flags definitions + * @{ + */ +#define HASH_FLAG_DINIS HASH_SR_DINIS /*!< 16 locations are free in the DIN : a new block can be entered in the Peripheral */ +#define HASH_FLAG_DCIS HASH_SR_DCIS /*!< Digest calculation complete */ +#define HASH_FLAG_DMAS HASH_SR_DMAS /*!< DMA interface is enabled (DMAE=1) or a transfer is ongoing */ +#define HASH_FLAG_BUSY HASH_SR_BUSY /*!< The hash core is Busy, processing a block of data */ +#define HASH_FLAG_DINNE HASH_CR_DINNE /*!< DIN not empty : the input buffer contains at least one word of data */ + +/** + * @} + */ + +/** @defgroup HASH_interrupts_definition HASH interrupts definitions + * @{ + */ +#define HASH_IT_DINI HASH_IMR_DINIE /*!< A new block can be entered into the input buffer (DIN) */ +#define HASH_IT_DCI HASH_IMR_DCIE /*!< Digest calculation complete */ + +/** + * @} + */ + +/** @defgroup HASH_Error_Definition HASH Error Definition + * @{ + */ +#define HAL_HASH_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_HASH_ERROR_IT 0x00000001U /*!< IT-based process error */ +#define HAL_HASH_ERROR_DMA 0x00000002U /*!< DMA-based process error */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1U) +#define HAL_HASH_ERROR_INVALID_CALLBACK 0x00000004U /*!< Invalid Callback error */ +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup HASH_Exported_Macros HASH Exported Macros + * @{ + */ + +/** @brief Check whether or not the specified HASH flag is set. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg @ref HASH_FLAG_DINIS A new block can be entered into the input buffer. + * @arg @ref HASH_FLAG_DCIS Digest calculation complete. + * @arg @ref HASH_FLAG_DMAS DMA interface is enabled (DMAE=1) or a transfer is ongoing. + * @arg @ref HASH_FLAG_BUSY The hash core is Busy : processing a block of data. + * @arg @ref HASH_FLAG_DINNE DIN not empty : the input buffer contains at least one word of data. + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_HASH_GET_FLAG(__FLAG__) (((__FLAG__) > 8U) ? \ + ((HASH->CR & (__FLAG__)) == (__FLAG__)) :\ + ((HASH->SR & (__FLAG__)) == (__FLAG__)) ) + + +/** @brief Clear the specified HASH flag. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be one of the following values: + * @arg @ref HASH_FLAG_DINIS A new block can be entered into the input buffer. + * @arg @ref HASH_FLAG_DCIS Digest calculation complete + * @retval None + */ +#define __HAL_HASH_CLEAR_FLAG(__FLAG__) CLEAR_BIT(HASH->SR, (__FLAG__)) + + +/** @brief Enable the specified HASH interrupt. + * @param __INTERRUPT__ specifies the HASH interrupt source to enable. + * This parameter can be one of the following values: + * @arg @ref HASH_IT_DINI A new block can be entered into the input buffer (DIN) + * @arg @ref HASH_IT_DCI Digest calculation complete + * @retval None + */ +#define __HAL_HASH_ENABLE_IT(__INTERRUPT__) SET_BIT(HASH->IMR, (__INTERRUPT__)) + +/** @brief Disable the specified HASH interrupt. + * @param __INTERRUPT__ specifies the HASH interrupt source to disable. + * This parameter can be one of the following values: + * @arg @ref HASH_IT_DINI A new block can be entered into the input buffer (DIN) + * @arg @ref HASH_IT_DCI Digest calculation complete + * @retval None + */ +#define __HAL_HASH_DISABLE_IT(__INTERRUPT__) CLEAR_BIT(HASH->IMR, (__INTERRUPT__)) + +/** @brief Reset HASH handle state. + * @param __HANDLE__ HASH handle. + * @retval None + */ + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) +#define __HAL_HASH_RESET_HANDLE_STATE(__HANDLE__) do{\ + (__HANDLE__)->State = HAL_HASH_STATE_RESET;\ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + }while(0) +#else +#define __HAL_HASH_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_HASH_STATE_RESET) +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + +/** @brief Reset HASH handle status. + * @param __HANDLE__ HASH handle. + * @retval None + */ +#define __HAL_HASH_RESET_HANDLE_STATUS(__HANDLE__) ((__HANDLE__)->Status = HAL_OK) + +/** + * @brief Enable the multi-buffer DMA transfer mode. + * @note This bit is set when hashing large files when multiple DMA transfers are needed. + * @retval None + */ +#define __HAL_HASH_SET_MDMAT() SET_BIT(HASH->CR, HASH_CR_MDMAT) + +/** + * @brief Disable the multi-buffer DMA transfer mode. + * @retval None + */ +#define __HAL_HASH_RESET_MDMAT() CLEAR_BIT(HASH->CR, HASH_CR_MDMAT) + + +/** + * @brief Start the digest computation. + * @retval None + */ +#define __HAL_HASH_START_DIGEST() SET_BIT(HASH->STR, HASH_STR_DCAL) + +/** + * @brief Set the number of valid bits in the last word written in data register DIN. + * @param __SIZE__ size in bytes of last data written in Data register. + * @retval None + */ +#define __HAL_HASH_SET_NBVALIDBITS(__SIZE__) MODIFY_REG(HASH->STR, HASH_STR_NBLW, 8U * ((__SIZE__) % 4U)) + +/** + * @brief Reset the HASH core. + * @retval None + */ +#define __HAL_HASH_INIT() SET_BIT(HASH->CR, HASH_CR_INIT) + +/** + * @} + */ + + +/* Private macros --------------------------------------------------------*/ +/** @defgroup HASH_Private_Macros HASH Private Macros + * @{ + */ +/** + * @brief Return digest length in bytes. + * @retval Digest length + */ +#if defined(HASH_CR_MDMAT) +#define HASH_DIGEST_LENGTH() ((READ_BIT(HASH->CR, HASH_CR_ALGO) == HASH_ALGOSELECTION_SHA1) ? 20U : \ + ((READ_BIT(HASH->CR, HASH_CR_ALGO) == HASH_ALGOSELECTION_SHA224) ? 28U : \ + ((READ_BIT(HASH->CR, HASH_CR_ALGO) == HASH_ALGOSELECTION_SHA256) ? 32U : 16U ) ) ) +#else +#define HASH_DIGEST_LENGTH() ((READ_BIT(HASH->CR, HASH_CR_ALGO) == HASH_ALGOSELECTION_SHA1) ? 20U : 16) +#endif /* HASH_CR_MDMAT*/ +/** + * @brief Return number of words already pushed in the FIFO. + * @retval Number of words already pushed in the FIFO + */ +#define HASH_NBW_PUSHED() ((READ_BIT(HASH->CR, HASH_CR_NBW)) >> 8U) + +/** + * @brief Ensure that HASH input data type is valid. + * @param __DATATYPE__ HASH input data type. + * @retval SET (__DATATYPE__ is valid) or RESET (__DATATYPE__ is invalid) + */ +#define IS_HASH_DATATYPE(__DATATYPE__) (((__DATATYPE__) == HASH_DATATYPE_32B)|| \ + ((__DATATYPE__) == HASH_DATATYPE_16B)|| \ + ((__DATATYPE__) == HASH_DATATYPE_8B) || \ + ((__DATATYPE__) == HASH_DATATYPE_1B)) + +/** + * @brief Ensure that input data buffer size is valid for multi-buffer HASH + * processing in DMA mode. + * @note This check is valid only for multi-buffer HASH processing in DMA mode. + * @param __SIZE__ input data buffer size. + * @retval SET (__SIZE__ is valid) or RESET (__SIZE__ is invalid) + */ +#define IS_HASH_DMA_MULTIBUFFER_SIZE(__SIZE__) ((READ_BIT(HASH->CR, HASH_CR_MDMAT) == 0U) || (((__SIZE__) % 4U) == 0U)) + +/** + * @brief Ensure that input data buffer size is valid for multi-buffer HMAC + * processing in DMA mode. + * @note This check is valid only for multi-buffer HMAC processing in DMA mode. + * @param __HANDLE__ HASH handle. + * @param __SIZE__ input data buffer size. + * @retval SET (__SIZE__ is valid) or RESET (__SIZE__ is invalid) + */ +#define IS_HMAC_DMA_MULTIBUFFER_SIZE(__HANDLE__,__SIZE__) ((((__HANDLE__)->DigestCalculationDisable) == RESET)\ + || (((__SIZE__) % 4U) == 0U)) +/** + * @brief Ensure that handle phase is set to HASH processing. + * @param __HANDLE__ HASH handle. + * @retval SET (handle phase is set to HASH processing) or RESET (handle phase is not set to HASH processing) + */ +#define IS_HASH_PROCESSING(__HANDLE__) ((__HANDLE__)->Phase == HAL_HASH_PHASE_PROCESS) + +/** + * @brief Ensure that handle phase is set to HMAC processing. + * @param __HANDLE__ HASH handle. + * @retval SET (handle phase is set to HMAC processing) or RESET (handle phase is not set to HMAC processing) + */ +#define IS_HMAC_PROCESSING(__HANDLE__) (((__HANDLE__)->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || \ + ((__HANDLE__)->Phase == HAL_HASH_PHASE_HMAC_STEP_2) || \ + ((__HANDLE__)->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) + +/** + * @} + */ + +/* Include HASH HAL Extended module */ +#include "stm32f4xx_hal_hash_ex.h" +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup HASH_Exported_Functions HASH Exported Functions + * @{ + */ + +/** @addtogroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization methods **********************************/ +HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash); +HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash); +void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash); +void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash); +void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash); +void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash); +void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash); +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, + pHASH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode + * @{ + */ + + +/* HASH processing using polling *********************************************/ +HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout); +HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout); +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); + + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode + * @{ + */ + +/* HASH processing using IT **************************************************/ +HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash); +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode + * @{ + */ + +/* HASH processing using DMA *************************************************/ +HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout); + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode + * @{ + */ + +/* HASH-MAC processing using polling *****************************************/ +HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout); +HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout); + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode + * @{ + */ + +HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode + * @{ + */ + +/* HASH-HMAC processing using DMA ********************************************/ +HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); + +/** + * @} + */ + +/** @addtogroup HASH_Exported_Functions_Group8 Peripheral states functions + * @{ + */ + + +/* Peripheral State methods **************************************************/ +HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash); +HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash); +void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer); +void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer); +void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash); +HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash); +uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash); + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions -----------------------------------------------------------*/ + +/** @addtogroup HASH_Private_Functions HASH Private Functions + * @{ + */ + +/* Private functions */ +HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout, uint32_t Algorithm); +HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm); +HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm); +HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Algorithm); +HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm); +HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout, uint32_t Algorithm); +HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Algorithm); +HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm); + +/** + * @} + */ + +/** + * @} + */ +#endif /* HASH*/ +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_HASH_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h new file mode 100644 index 0000000..91e65dc --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hash_ex.h @@ -0,0 +1,175 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hash_ex.h + * @author MCD Application Team + * @brief Header file of HASH 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 STM32F4xx_HAL_HASH_EX_H +#define STM32F4xx_HAL_HASH_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (HASH) +/** @addtogroup HASHEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ + + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup HASHEx_Exported_Functions HASH Extended Exported Functions + * @{ + */ + +/** @addtogroup HASHEx_Exported_Functions_Group1 HASH extended processing functions in polling mode + * @{ + */ + +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); + +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group2 HASH extended processing functions in interrupt mode + * @{ + */ + +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); + +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group3 HASH extended processing functions in DMA mode + * @{ + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout); + +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group4 HMAC extended processing functions in polling mode + * @{ + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout); +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group5 HMAC extended processing functions in interrupt mode + * @{ + */ + +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer); + +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group6 HMAC extended processing functions in DMA mode + * @{ + */ + +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); + +/** + * @} + */ + +/** @addtogroup HASHEx_Exported_Functions_Group7 Multi-buffer HMAC extended processing functions in DMA mode + * @{ + */ + +HAL_StatusTypeDef HAL_HMACEx_MD5_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); + +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); + +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* HASH*/ +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_HASH_EX_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h new file mode 100644 index 0000000..9cd1486 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_hcd.h @@ -0,0 +1,316 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hcd.h + * @author MCD Application Team + * @brief Header file of HCD 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 STM32F4xx_HAL_HCD_H +#define STM32F4xx_HAL_HCD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_usb.h" + +#if defined (USB_OTG_FS) || defined (USB_OTG_HS) +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup HCD HCD + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup HCD_Exported_Types HCD Exported Types + * @{ + */ + +/** @defgroup HCD_Exported_Types_Group1 HCD State Structure definition + * @{ + */ +typedef enum +{ + HAL_HCD_STATE_RESET = 0x00, + HAL_HCD_STATE_READY = 0x01, + HAL_HCD_STATE_ERROR = 0x02, + HAL_HCD_STATE_BUSY = 0x03, + HAL_HCD_STATE_TIMEOUT = 0x04 +} HCD_StateTypeDef; + +typedef USB_OTG_GlobalTypeDef HCD_TypeDef; +typedef USB_OTG_CfgTypeDef HCD_InitTypeDef; +typedef USB_OTG_HCTypeDef HCD_HCTypeDef; +typedef USB_OTG_URBStateTypeDef HCD_URBStateTypeDef; +typedef USB_OTG_HCStateTypeDef HCD_HCStateTypeDef; +/** + * @} + */ + +/** @defgroup HCD_Exported_Types_Group2 HCD Handle Structure definition + * @{ + */ +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) +typedef struct __HCD_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ +{ + HCD_TypeDef *Instance; /*!< Register base address */ + HCD_InitTypeDef Init; /*!< HCD required parameters */ + HCD_HCTypeDef hc[16]; /*!< Host channels parameters */ + HAL_LockTypeDef Lock; /*!< HCD peripheral status */ + __IO HCD_StateTypeDef State; /*!< HCD communication state */ + __IO uint32_t ErrorCode; /*!< HCD Error code */ + void *pData; /*!< Pointer Stack Handler */ +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + void (* SOFCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD SOF callback */ + void (* ConnectCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Connect callback */ + void (* DisconnectCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Disconnect callback */ + void (* PortEnabledCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Port Enable callback */ + void (* PortDisabledCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Port Disable callback */ + void (* HC_NotifyURBChangeCallback)(struct __HCD_HandleTypeDef *hhcd, uint8_t chnum, + HCD_URBStateTypeDef urb_state); /*!< USB OTG HCD Host Channel Notify URB Change callback */ + + void (* MspInitCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Msp Init callback */ + void (* MspDeInitCallback)(struct __HCD_HandleTypeDef *hhcd); /*!< USB OTG HCD Msp DeInit callback */ +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ +} HCD_HandleTypeDef; +/** + * @} + */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup HCD_Exported_Constants HCD Exported Constants + * @{ + */ + +/** @defgroup HCD_Speed HCD Speed + * @{ + */ +#define HCD_SPEED_HIGH USBH_HS_SPEED +#define HCD_SPEED_FULL USBH_FSLS_SPEED +#define HCD_SPEED_LOW USBH_FSLS_SPEED +/** + * @} + */ + +/** @defgroup HCD_Device_Speed HCD Device Speed + * @{ + */ +#define HCD_DEVICE_SPEED_HIGH 0U +#define HCD_DEVICE_SPEED_FULL 1U +#define HCD_DEVICE_SPEED_LOW 2U +/** + * @} + */ + +/** @defgroup HCD_PHY_Module HCD PHY Module + * @{ + */ +#define HCD_PHY_ULPI 1U +#define HCD_PHY_EMBEDDED 2U +/** + * @} + */ + +/** @defgroup HCD_Error_Code_definition HCD Error Code definition + * @brief HCD Error Code definition + * @{ + */ +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) +#define HAL_HCD_ERROR_INVALID_CALLBACK (0x00000010U) /*!< Invalid Callback error */ +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup HCD_Exported_Macros HCD Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ +#define __HAL_HCD_ENABLE(__HANDLE__) (void)USB_EnableGlobalInt ((__HANDLE__)->Instance) +#define __HAL_HCD_DISABLE(__HANDLE__) (void)USB_DisableGlobalInt ((__HANDLE__)->Instance) + +#define __HAL_HCD_GET_FLAG(__HANDLE__, __INTERRUPT__) ((USB_ReadInterrupts((__HANDLE__)->Instance)\ + & (__INTERRUPT__)) == (__INTERRUPT__)) +#define __HAL_HCD_CLEAR_FLAG(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->GINTSTS) = (__INTERRUPT__)) +#define __HAL_HCD_IS_INVALID_INTERRUPT(__HANDLE__) (USB_ReadInterrupts((__HANDLE__)->Instance) == 0U) + +#define __HAL_HCD_CLEAR_HC_INT(chnum, __INTERRUPT__) (USBx_HC(chnum)->HCINT = (__INTERRUPT__)) +#define __HAL_HCD_MASK_HALT_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINTMSK_CHHM) +#define __HAL_HCD_UNMASK_HALT_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM) +#define __HAL_HCD_MASK_ACK_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK &= ~USB_OTG_HCINTMSK_ACKM) +#define __HAL_HCD_UNMASK_ACK_HC_INT(chnum) (USBx_HC(chnum)->HCINTMSK |= USB_OTG_HCINTMSK_ACKM) +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup HCD_Exported_Functions HCD Exported Functions + * @{ + */ + +/** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd); +HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd); +HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, + uint8_t epnum, uint8_t dev_address, + uint8_t speed, uint8_t ep_type, uint16_t mps); + +HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num); +void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd); +void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd); + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) +/** @defgroup HAL_HCD_Callback_ID_enumeration_definition HAL USB OTG HCD Callback ID enumeration definition + * @brief HAL USB OTG HCD Callback ID enumeration definition + * @{ + */ +typedef enum +{ + HAL_HCD_SOF_CB_ID = 0x01, /*!< USB HCD SOF callback ID */ + HAL_HCD_CONNECT_CB_ID = 0x02, /*!< USB HCD Connect callback ID */ + HAL_HCD_DISCONNECT_CB_ID = 0x03, /*!< USB HCD Disconnect callback ID */ + HAL_HCD_PORT_ENABLED_CB_ID = 0x04, /*!< USB HCD Port Enable callback ID */ + HAL_HCD_PORT_DISABLED_CB_ID = 0x05, /*!< USB HCD Port Disable callback ID */ + + HAL_HCD_MSPINIT_CB_ID = 0x06, /*!< USB HCD MspInit callback ID */ + HAL_HCD_MSPDEINIT_CB_ID = 0x07 /*!< USB HCD MspDeInit callback ID */ + +} HAL_HCD_CallbackIDTypeDef; +/** + * @} + */ + +/** @defgroup HAL_HCD_Callback_pointer_definition HAL USB OTG HCD Callback pointer definition + * @brief HAL USB OTG HCD Callback pointer definition + * @{ + */ + +typedef void (*pHCD_CallbackTypeDef)(HCD_HandleTypeDef *hhcd); /*!< pointer to a common USB OTG HCD callback function */ +typedef void (*pHCD_HC_NotifyURBChangeCallbackTypeDef)(HCD_HandleTypeDef *hhcd, + uint8_t epnum, + HCD_URBStateTypeDef urb_state); /*!< pointer to USB OTG HCD host channel callback */ +/** + * @} + */ + +HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd, + HAL_HCD_CallbackIDTypeDef CallbackID, + pHCD_CallbackTypeDef pCallback); + +HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, + HAL_HCD_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd, + pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback); + +HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* I/O operation functions ***************************************************/ +/** @addtogroup HCD_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, uint8_t ch_num, + uint8_t direction, uint8_t ep_type, + uint8_t token, uint8_t *pbuff, + uint16_t length, uint8_t do_ping); + +/* Non-Blocking mode: Interrupt */ +void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd); +void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd); +void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd); +void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd); +void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd); +void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd); +void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd); +void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, + HCD_URBStateTypeDef urb_state); +/** + * @} + */ + +/* Peripheral Control functions **********************************************/ +/** @addtogroup HCD_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd); +HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd); +HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd); +/** + * @} + */ + +/* Peripheral State functions ************************************************/ +/** @addtogroup HCD_Exported_Functions_Group4 Peripheral State functions + * @{ + */ +HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd); +HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum); +HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum); +uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum); +uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd); +uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd); + +/** + * @} + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup HCD_Private_Macros HCD Private Macros + * @{ + */ +/** + * @} + */ +/* Private functions prototypes ----------------------------------------------*/ + +/** + * @} + */ +/** + * @} + */ +#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_HCD_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h new file mode 100644 index 0000000..9a7a67e --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h @@ -0,0 +1,741 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c.h + * @author MCD Application Team + * @brief Header file of I2C 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 __STM32F4xx_HAL_I2C_H +#define __STM32F4xx_HAL_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2C + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup I2C_Exported_Types I2C Exported Types + * @{ + */ + +/** @defgroup I2C_Configuration_Structure_definition I2C Configuration Structure definition + * @brief I2C Configuration Structure definition + * @{ + */ +typedef struct +{ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref I2C_addressing_mode */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref I2C_dual_addressing_mode */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is selected + This parameter can be a 7-bit address. */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref I2C_general_call_addressing_mode */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref I2C_nostretch_mode */ + +} I2C_InitTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_state_structure_definition HAL state structure definition + * @brief HAL State structure definition + * @note HAL I2C State value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : Abort (Abort user request on going) + * 10 : Timeout + * 11 : Error + * b5 Peripheral initialization status + * 0 : Reset (Peripheral not initialized) + * 1 : Init done (Peripheral initialized and ready to use. HAL I2C Init function called) + * b4 (not used) + * x : Should be set to 0 + * b3 + * 0 : Ready or Busy (No Listen mode ongoing) + * 1 : Listen (Peripheral in Address Listen Mode) + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (Peripheral busy with some configuration or internal operations) + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + * @{ + */ +typedef enum +{ + HAL_I2C_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_I2C_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_I2C_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_I2C_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_I2C_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_I2C_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_I2C_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_I2C_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_I2C_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_I2C_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_I2C_STATE_ERROR = 0xE0U /*!< Error */ + +} HAL_I2C_StateTypeDef; + +/** + * @} + */ + +/** @defgroup HAL_mode_structure_definition HAL mode structure definition + * @brief HAL Mode structure definition + * @note HAL I2C Mode value coding follow below described bitmap :\n + * b7 (not used)\n + * x : Should be set to 0\n + * b6\n + * 0 : None\n + * 1 : Memory (HAL I2C communication is in Memory Mode)\n + * b5\n + * 0 : None\n + * 1 : Slave (HAL I2C communication is in Slave Mode)\n + * b4\n + * 0 : None\n + * 1 : Master (HAL I2C communication is in Master Mode)\n + * b3-b2-b1-b0 (not used)\n + * xxxx : Should be set to 0000 + * @{ + */ +typedef enum +{ + HAL_I2C_MODE_NONE = 0x00U, /*!< No I2C communication on going */ + HAL_I2C_MODE_MASTER = 0x10U, /*!< I2C communication is in Master Mode */ + HAL_I2C_MODE_SLAVE = 0x20U, /*!< I2C communication is in Slave Mode */ + HAL_I2C_MODE_MEM = 0x40U /*!< I2C communication is in Memory Mode */ + +} HAL_I2C_ModeTypeDef; + +/** + * @} + */ + +/** @defgroup I2C_Error_Code_definition I2C Error Code definition + * @brief I2C Error Code definition + * @{ + */ +#define HAL_I2C_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_I2C_ERROR_BERR 0x00000001U /*!< BERR error */ +#define HAL_I2C_ERROR_ARLO 0x00000002U /*!< ARLO error */ +#define HAL_I2C_ERROR_AF 0x00000004U /*!< AF error */ +#define HAL_I2C_ERROR_OVR 0x00000008U /*!< OVR error */ +#define HAL_I2C_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#define HAL_I2C_ERROR_TIMEOUT 0x00000020U /*!< Timeout Error */ +#define HAL_I2C_ERROR_SIZE 0x00000040U /*!< Size Management error */ +#define HAL_I2C_ERROR_DMA_PARAM 0x00000080U /*!< DMA Parameter Error */ +#define HAL_I2C_WRONG_START 0x00000200U /*!< Wrong start Error */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +#define HAL_I2C_ERROR_INVALID_CALLBACK 0x00000100U /*!< Invalid Callback error */ +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup I2C_handle_Structure_definition I2C handle Structure definition + * @brief I2C handle Structure definition + * @{ + */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +typedef struct __I2C_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ +{ + I2C_TypeDef *Instance; /*!< I2C registers base address */ + + I2C_InitTypeDef Init; /*!< I2C communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to I2C transfer buffer */ + + uint16_t XferSize; /*!< I2C transfer size */ + + __IO uint16_t XferCount; /*!< I2C transfer counter */ + + __IO uint32_t XferOptions; /*!< I2C transfer options */ + + __IO uint32_t PreviousState; /*!< I2C communication Previous state and mode + context for internal usage */ + + DMA_HandleTypeDef *hdmatx; /*!< I2C Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< I2C Rx DMA handle parameters */ + + HAL_LockTypeDef Lock; /*!< I2C locking object */ + + __IO HAL_I2C_StateTypeDef State; /*!< I2C communication state */ + + __IO HAL_I2C_ModeTypeDef Mode; /*!< I2C communication mode */ + + __IO uint32_t ErrorCode; /*!< I2C Error code */ + + __IO uint32_t Devaddress; /*!< I2C Target device address */ + + __IO uint32_t Memaddress; /*!< I2C Target memory address */ + + __IO uint32_t MemaddSize; /*!< I2C Target memory address size */ + + __IO uint32_t EventCount; /*!< I2C Event counter */ + + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Tx Transfer completed callback */ + void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Rx Transfer completed callback */ + void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Tx Transfer completed callback */ + void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Rx Transfer completed callback */ + void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Listen Complete callback */ + void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Tx Transfer completed callback */ + void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Rx Transfer completed callback */ + void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Error callback */ + void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Abort callback */ + + void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< I2C Slave Address Match callback */ + + void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp Init callback */ + void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp DeInit callback */ + +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ +} I2C_HandleTypeDef; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +/** + * @brief HAL I2C Callback ID enumeration definition + */ +typedef enum +{ + HAL_I2C_MASTER_TX_COMPLETE_CB_ID = 0x00U, /*!< I2C Master Tx Transfer completed callback ID */ + HAL_I2C_MASTER_RX_COMPLETE_CB_ID = 0x01U, /*!< I2C Master Rx Transfer completed callback ID */ + HAL_I2C_SLAVE_TX_COMPLETE_CB_ID = 0x02U, /*!< I2C Slave Tx Transfer completed callback ID */ + HAL_I2C_SLAVE_RX_COMPLETE_CB_ID = 0x03U, /*!< I2C Slave Rx Transfer completed callback ID */ + HAL_I2C_LISTEN_COMPLETE_CB_ID = 0x04U, /*!< I2C Listen Complete callback ID */ + HAL_I2C_MEM_TX_COMPLETE_CB_ID = 0x05U, /*!< I2C Memory Tx Transfer callback ID */ + HAL_I2C_MEM_RX_COMPLETE_CB_ID = 0x06U, /*!< I2C Memory Rx Transfer completed callback ID */ + HAL_I2C_ERROR_CB_ID = 0x07U, /*!< I2C Error callback ID */ + HAL_I2C_ABORT_CB_ID = 0x08U, /*!< I2C Abort callback ID */ + + HAL_I2C_MSPINIT_CB_ID = 0x09U, /*!< I2C Msp Init callback ID */ + HAL_I2C_MSPDEINIT_CB_ID = 0x0AU /*!< I2C Msp DeInit callback ID */ + +} HAL_I2C_CallbackIDTypeDef; + +/** + * @brief HAL I2C Callback pointer definition + */ +typedef void (*pI2C_CallbackTypeDef)(I2C_HandleTypeDef *hi2c); /*!< pointer to an I2C callback function */ +typedef void (*pI2C_AddrCallbackTypeDef)(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< pointer to an I2C Address Match callback function */ + +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** + * @} + */ +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2C_duty_cycle_in_fast_mode I2C duty cycle in fast mode + * @{ + */ +#define I2C_DUTYCYCLE_2 0x00000000U +#define I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY +/** + * @} + */ + +/** @defgroup I2C_addressing_mode I2C addressing mode + * @{ + */ +#define I2C_ADDRESSINGMODE_7BIT 0x00004000U +#define I2C_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) +/** + * @} + */ + +/** @defgroup I2C_dual_addressing_mode I2C dual addressing mode + * @{ + */ +#define I2C_DUALADDRESS_DISABLE 0x00000000U +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL +/** + * @} + */ + +/** @defgroup I2C_general_call_addressing_mode I2C general call addressing mode + * @{ + */ +#define I2C_GENERALCALL_DISABLE 0x00000000U +#define I2C_GENERALCALL_ENABLE I2C_CR1_ENGC +/** + * @} + */ + +/** @defgroup I2C_nostretch_mode I2C nostretch mode + * @{ + */ +#define I2C_NOSTRETCH_DISABLE 0x00000000U +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup I2C_Memory_Address_Size I2C Memory Address Size + * @{ + */ +#define I2C_MEMADD_SIZE_8BIT 0x00000001U +#define I2C_MEMADD_SIZE_16BIT 0x00000010U +/** + * @} + */ + +/** @defgroup I2C_XferDirection_definition I2C XferDirection definition + * @{ + */ +#define I2C_DIRECTION_RECEIVE 0x00000000U +#define I2C_DIRECTION_TRANSMIT 0x00000001U +/** + * @} + */ + +/** @defgroup I2C_XferOptions_definition I2C XferOptions definition + * @{ + */ +#define I2C_FIRST_FRAME 0x00000001U +#define I2C_FIRST_AND_NEXT_FRAME 0x00000002U +#define I2C_NEXT_FRAME 0x00000004U +#define I2C_FIRST_AND_LAST_FRAME 0x00000008U +#define I2C_LAST_FRAME_NO_STOP 0x00000010U +#define I2C_LAST_FRAME 0x00000020U + +/* List of XferOptions in usage of : + * 1- Restart condition in all use cases (direction change or not) + */ +#define I2C_OTHER_FRAME (0x00AA0000U) +#define I2C_OTHER_AND_LAST_FRAME (0xAA000000U) +/** + * @} + */ + +/** @defgroup I2C_Interrupt_configuration_definition I2C Interrupt configuration definition + * @brief I2C Interrupt definition + * Elements values convention: 0xXXXXXXXX + * - XXXXXXXX : Interrupt control mask + * @{ + */ +#define I2C_IT_BUF I2C_CR2_ITBUFEN +#define I2C_IT_EVT I2C_CR2_ITEVTEN +#define I2C_IT_ERR I2C_CR2_ITERREN +/** + * @} + */ + +/** @defgroup I2C_Flag_definition I2C Flag definition + * @{ + */ + +#define I2C_FLAG_OVR 0x00010800U +#define I2C_FLAG_AF 0x00010400U +#define I2C_FLAG_ARLO 0x00010200U +#define I2C_FLAG_BERR 0x00010100U +#define I2C_FLAG_TXE 0x00010080U +#define I2C_FLAG_RXNE 0x00010040U +#define I2C_FLAG_STOPF 0x00010010U +#define I2C_FLAG_ADD10 0x00010008U +#define I2C_FLAG_BTF 0x00010004U +#define I2C_FLAG_ADDR 0x00010002U +#define I2C_FLAG_SB 0x00010001U +#define I2C_FLAG_DUALF 0x00100080U +#define I2C_FLAG_GENCALL 0x00100010U +#define I2C_FLAG_TRA 0x00100004U +#define I2C_FLAG_BUSY 0x00100002U +#define I2C_FLAG_MSL 0x00100001U +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Macros I2C Exported Macros + * @{ + */ + +/** @brief Reset I2C handle state. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_I2C_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_I2C_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2C_STATE_RESET) +#endif + +/** @brief Enable or disable the specified I2C interrupts. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg I2C_IT_BUF: Buffer interrupt enable + * @arg I2C_IT_EVT: Event interrupt enable + * @arg I2C_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_I2C_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2,(__INTERRUPT__)) +#define __HAL_I2C_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) + +/** @brief Checks if the specified I2C interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the I2C Handle. + * @param __INTERRUPT__ specifies the I2C interrupt source to check. + * This parameter can be one of the following values: + * @arg I2C_IT_BUF: Buffer interrupt enable + * @arg I2C_IT_EVT: Event interrupt enable + * @arg I2C_IT_ERR: Error interrupt enable + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_I2C_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified I2C flag is set or not. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2C_FLAG_OVR: Overrun/Underrun flag + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag + * @arg I2C_FLAG_BERR: Bus error flag + * @arg I2C_FLAG_TXE: Data register empty flag + * @arg I2C_FLAG_RXNE: Data register not empty flag + * @arg I2C_FLAG_STOPF: Stop detection flag + * @arg I2C_FLAG_ADD10: 10-bit header sent flag + * @arg I2C_FLAG_BTF: Byte transfer finished flag + * @arg I2C_FLAG_ADDR: Address sent flag + * Address matched flag + * @arg I2C_FLAG_SB: Start bit flag + * @arg I2C_FLAG_DUALF: Dual flag + * @arg I2C_FLAG_GENCALL: General call header flag + * @arg I2C_FLAG_TRA: Transmitter/Receiver flag + * @arg I2C_FLAG_BUSY: Bus busy flag + * @arg I2C_FLAG_MSL: Master/Slave flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_I2C_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U) ? \ + (((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET) : \ + (((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET)) + +/** @brief Clears the I2C pending flags which are cleared by writing 0 in a specific bit. + * @param __HANDLE__ specifies the I2C Handle. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg I2C_FLAG_AF: Acknowledge failure flag + * @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg I2C_FLAG_BERR: Bus error flag + * @retval None + */ +#define __HAL_I2C_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__) & I2C_FLAG_MASK)) + +/** @brief Clears the I2C ADDR pending flag. + * @param __HANDLE__ specifies the I2C Handle. + * This parameter can be I2C where x: 1, 2, or 3 to select the I2C peripheral. + * @retval None + */ +#define __HAL_I2C_CLEAR_ADDRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + tmpreg = (__HANDLE__)->Instance->SR2; \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Clears the I2C STOPF pending flag. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_CLEAR_STOPFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE); \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Enable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE) + +/** @brief Disable the specified I2C peripheral. + * @param __HANDLE__ specifies the I2C Handle. + * @retval None + */ +#define __HAL_I2C_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_PE) + +/** + * @} + */ + +/* Include I2C HAL Extension module */ +#include "stm32f4xx_hal_i2c_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2C_Exported_Functions + * @{ + */ + +/** @addtogroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +/* Initialization and de-initialization functions******************************/ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID, pI2C_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_I2C_RegisterAddrCallback(I2C_HandleTypeDef *hi2c, pI2C_AddrCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* IO operation functions ****************************************************/ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); + +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c); +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress); + +/******* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +/** + * @} + */ + +/** @addtogroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* I2C IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c); +void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/** @addtogroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @{ + */ +/* Peripheral State, Mode and Error functions *********************************/ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c); +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c); +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c); + +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Constants I2C Private Constants + * @{ + */ +#define I2C_FLAG_MASK 0x0000FFFFU +#define I2C_MIN_PCLK_FREQ_STANDARD 2000000U /*!< 2 MHz */ +#define I2C_MIN_PCLK_FREQ_FAST 4000000U /*!< 4 MHz */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2C_Private_Macros I2C Private Macros + * @{ + */ + +#define I2C_MIN_PCLK_FREQ(__PCLK__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__PCLK__) < I2C_MIN_PCLK_FREQ_STANDARD) : ((__PCLK__) < I2C_MIN_PCLK_FREQ_FAST)) +#define I2C_CCR_CALCULATION(__PCLK__, __SPEED__, __COEFF__) (((((__PCLK__) - 1U)/((__SPEED__) * (__COEFF__))) + 1U) & I2C_CCR_CCR) +#define I2C_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U) +#define I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (((__SPEED__) <= 100000U) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U)) +#define I2C_SPEED_STANDARD(__PCLK__, __SPEED__) ((I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U) < 4U)? 4U:I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 2U)) +#define I2C_SPEED_FAST(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__DUTYCYCLE__) == I2C_DUTYCYCLE_2)? I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 3U) : (I2C_CCR_CALCULATION((__PCLK__), (__SPEED__), 25U) | I2C_DUTYCYCLE_16_9)) +#define I2C_SPEED(__PCLK__, __SPEED__, __DUTYCYCLE__) (((__SPEED__) <= 100000U)? (I2C_SPEED_STANDARD((__PCLK__), (__SPEED__))) : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__)) & I2C_CCR_CCR) == 0U)? 1U : \ + ((I2C_SPEED_FAST((__PCLK__), (__SPEED__), (__DUTYCYCLE__))) | I2C_CCR_FS)) + +#define I2C_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0))) +#define I2C_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) + +#define I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) +#define I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0))) +#define I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1)))) + +#define I2C_MEM_ADD_MSB(__ADDRESS__) ((uint8_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0xFF00)) >> 8))) +#define I2C_MEM_ADD_LSB(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) + +/** @defgroup I2C_IS_RTC_Definitions I2C Private macros to check input parameters + * @{ + */ +#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DUTYCYCLE_2) || \ + ((CYCLE) == I2C_DUTYCYCLE_16_9)) +#define IS_I2C_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == I2C_ADDRESSINGMODE_7BIT) || \ + ((ADDRESS) == I2C_ADDRESSINGMODE_10BIT)) +#define IS_I2C_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == I2C_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == I2C_DUALADDRESS_ENABLE)) +#define IS_I2C_GENERAL_CALL(CALL) (((CALL) == I2C_GENERALCALL_DISABLE) || \ + ((CALL) == I2C_GENERALCALL_ENABLE)) +#define IS_I2C_NO_STRETCH(STRETCH) (((STRETCH) == I2C_NOSTRETCH_DISABLE) || \ + ((STRETCH) == I2C_NOSTRETCH_ENABLE)) +#define IS_I2C_MEMADD_SIZE(SIZE) (((SIZE) == I2C_MEMADD_SIZE_8BIT) || \ + ((SIZE) == I2C_MEMADD_SIZE_16BIT)) +#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) > 0U) && ((SPEED) <= 400000U)) +#define IS_I2C_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & 0xFFFFFC00U) == 0U) +#define IS_I2C_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & 0xFFFFFF01U) == 0U) +#define IS_I2C_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_FIRST_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_NEXT_FRAME) || \ + ((REQUEST) == I2C_NEXT_FRAME) || \ + ((REQUEST) == I2C_FIRST_AND_LAST_FRAME) || \ + ((REQUEST) == I2C_LAST_FRAME) || \ + ((REQUEST) == I2C_LAST_FRAME_NO_STOP) || \ + IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST)) + +#define IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == I2C_OTHER_FRAME) || \ + ((REQUEST) == I2C_OTHER_AND_LAST_FRAME)) + +#define I2C_CHECK_FLAG(__ISR__, __FLAG__) ((((__ISR__) & ((__FLAG__) & I2C_FLAG_MASK)) == ((__FLAG__) & I2C_FLAG_MASK)) ? SET : RESET) +#define I2C_CHECK_IT_SOURCE(__CR1__, __IT__) ((((__CR1__) & (__IT__)) == (__IT__)) ? SET : RESET) +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32F4xx_HAL_I2C_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h new file mode 100644 index 0000000..31ad99c --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c_ex.h @@ -0,0 +1,115 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c_ex.h + * @author MCD Application Team + * @brief Header file of I2C HAL Extension 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 __STM32F4xx_HAL_I2C_EX_H +#define __STM32F4xx_HAL_I2C_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2CEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2CEx_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2CEx_Analog_Filter I2C Analog Filter + * @{ + */ +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2CEx_Exported_Functions + * @{ + */ + +/** @addtogroup I2CEx_Exported_Functions_Group1 + * @{ + */ +/* Peripheral Control functions ************************************************/ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Constants I2C Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2CEx_Private_Macros I2C Private Macros + * @{ + */ +#define IS_I2C_ANALOG_FILTER(FILTER) (((FILTER) == I2C_ANALOGFILTER_ENABLE) || \ + ((FILTER) == I2C_ANALOGFILTER_DISABLE)) +#define IS_I2C_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_I2C_EX_H */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h new file mode 100644 index 0000000..66cee01 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s.h @@ -0,0 +1,618 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2s.h + * @author MCD Application Team + * @brief Header file of I2S 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 STM32F4xx_HAL_I2S_H +#define STM32F4xx_HAL_I2S_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup I2S + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup I2S_Exported_Types I2S Exported Types + * @{ + */ + +/** + * @brief I2S Init structure definition + */ +typedef struct +{ + uint32_t Mode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2S_Mode */ + + uint32_t Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref I2S_Standard */ + + uint32_t DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_Data_Format */ + + uint32_t MCLKOutput; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_MCLK_Output */ + + uint32_t AudioFreq; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_Audio_Frequency */ + + uint32_t CPOL; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_Clock_Polarity */ + + uint32_t ClockSource; /*!< Specifies the I2S Clock Source. + This parameter can be a value of @ref I2S_Clock_Source */ + uint32_t FullDuplexMode; /*!< Specifies the I2S FullDuplex mode. + This parameter can be a value of @ref I2S_FullDuplex_Mode */ +} I2S_InitTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_I2S_STATE_RESET = 0x00U, /*!< I2S not yet initialized or disabled */ + HAL_I2S_STATE_READY = 0x01U, /*!< I2S initialized and ready for use */ + HAL_I2S_STATE_BUSY = 0x02U, /*!< I2S internal process is ongoing */ + HAL_I2S_STATE_BUSY_TX = 0x03U, /*!< Data Transmission process is ongoing */ + HAL_I2S_STATE_BUSY_RX = 0x04U, /*!< Data Reception process is ongoing */ + HAL_I2S_STATE_BUSY_TX_RX = 0x05U, /*!< Data Transmission and Reception process is ongoing */ + HAL_I2S_STATE_TIMEOUT = 0x06U, /*!< I2S timeout state */ + HAL_I2S_STATE_ERROR = 0x07U /*!< I2S error state */ +} HAL_I2S_StateTypeDef; + +/** + * @brief I2S handle Structure definition + */ +typedef struct __I2S_HandleTypeDef +{ + SPI_TypeDef *Instance; /*!< I2S registers base address */ + + I2S_InitTypeDef Init; /*!< I2S communication parameters */ + + uint16_t *pTxBuffPtr; /*!< Pointer to I2S Tx transfer buffer */ + + __IO uint16_t TxXferSize; /*!< I2S Tx transfer size */ + + __IO uint16_t TxXferCount; /*!< I2S Tx transfer Counter */ + + uint16_t *pRxBuffPtr; /*!< Pointer to I2S Rx transfer buffer */ + + __IO uint16_t RxXferSize; /*!< I2S Rx transfer size */ + + __IO uint16_t RxXferCount; /*!< I2S Rx transfer counter + (This field is initialized at the + same value as transfer size at the + beginning of the transfer and + decremented when a sample is received + NbSamplesReceived = RxBufferSize-RxBufferCount) */ + void (*IrqHandlerISR)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S function pointer on IrqHandler */ + + DMA_HandleTypeDef *hdmatx; /*!< I2S Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< I2S Rx DMA handle parameters */ + + __IO HAL_LockTypeDef Lock; /*!< I2S locking object */ + + __IO HAL_I2S_StateTypeDef State; /*!< I2S communication state */ + + __IO uint32_t ErrorCode; /*!< I2S Error code + This parameter can be a value of @ref I2S_Error */ + +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + void (* TxCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Tx Completed callback */ + void (* RxCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Rx Completed callback */ + void (* TxRxCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S TxRx Completed callback */ + void (* TxHalfCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Tx Half Completed callback */ + void (* RxHalfCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Rx Half Completed callback */ + void (* TxRxHalfCpltCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S TxRx Half Completed callback */ + void (* ErrorCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Error callback */ + void (* MspInitCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Msp Init callback */ + void (* MspDeInitCallback)(struct __I2S_HandleTypeDef *hi2s); /*!< I2S Msp DeInit callback */ + +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} I2S_HandleTypeDef; + +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) +/** + * @brief HAL I2S Callback ID enumeration definition + */ +typedef enum +{ + HAL_I2S_TX_COMPLETE_CB_ID = 0x00U, /*!< I2S Tx Completed callback ID */ + HAL_I2S_RX_COMPLETE_CB_ID = 0x01U, /*!< I2S Rx Completed callback ID */ + HAL_I2S_TX_RX_COMPLETE_CB_ID = 0x02U, /*!< I2S TxRx Completed callback ID */ + HAL_I2S_TX_HALF_COMPLETE_CB_ID = 0x03U, /*!< I2S Tx Half Completed callback ID */ + HAL_I2S_RX_HALF_COMPLETE_CB_ID = 0x04U, /*!< I2S Rx Half Completed callback ID */ + HAL_I2S_TX_RX_HALF_COMPLETE_CB_ID = 0x05U, /*!< I2S TxRx Half Completed callback ID */ + HAL_I2S_ERROR_CB_ID = 0x06U, /*!< I2S Error callback ID */ + HAL_I2S_MSPINIT_CB_ID = 0x07U, /*!< I2S Msp Init callback ID */ + HAL_I2S_MSPDEINIT_CB_ID = 0x08U /*!< I2S Msp DeInit callback ID */ + +} HAL_I2S_CallbackIDTypeDef; + +/** + * @brief HAL I2S Callback pointer definition + */ +typedef void (*pI2S_CallbackTypeDef)(I2S_HandleTypeDef *hi2s); /*!< pointer to an I2S callback function */ + +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2S_Exported_Constants I2S Exported Constants + * @{ + */ +/** @defgroup I2S_Error I2S Error + * @{ + */ +#define HAL_I2S_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_I2S_ERROR_TIMEOUT (0x00000001U) /*!< Timeout error */ +#define HAL_I2S_ERROR_OVR (0x00000002U) /*!< OVR error */ +#define HAL_I2S_ERROR_UDR (0x00000004U) /*!< UDR error */ +#define HAL_I2S_ERROR_DMA (0x00000008U) /*!< DMA transfer error */ +#define HAL_I2S_ERROR_PRESCALER (0x00000010U) /*!< Prescaler Calculation error */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) +#define HAL_I2S_ERROR_INVALID_CALLBACK (0x00000020U) /*!< Invalid Callback error */ +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +#define HAL_I2S_ERROR_BUSY_LINE_RX (0x00000040U) /*!< Busy Rx Line error */ +/** + * @} + */ + +/** @defgroup I2S_Mode I2S Mode + * @{ + */ +#define I2S_MODE_SLAVE_TX (0x00000000U) +#define I2S_MODE_SLAVE_RX (SPI_I2SCFGR_I2SCFG_0) +#define I2S_MODE_MASTER_TX (SPI_I2SCFGR_I2SCFG_1) +#define I2S_MODE_MASTER_RX ((SPI_I2SCFGR_I2SCFG_0 | SPI_I2SCFGR_I2SCFG_1)) +/** + * @} + */ + +/** @defgroup I2S_Standard I2S Standard + * @{ + */ +#define I2S_STANDARD_PHILIPS (0x00000000U) +#define I2S_STANDARD_MSB (SPI_I2SCFGR_I2SSTD_0) +#define I2S_STANDARD_LSB (SPI_I2SCFGR_I2SSTD_1) +#define I2S_STANDARD_PCM_SHORT ((SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1)) +#define I2S_STANDARD_PCM_LONG ((SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1 | SPI_I2SCFGR_PCMSYNC)) +/** + * @} + */ + +/** @defgroup I2S_Data_Format I2S Data Format + * @{ + */ +#define I2S_DATAFORMAT_16B (0x00000000U) +#define I2S_DATAFORMAT_16B_EXTENDED (SPI_I2SCFGR_CHLEN) +#define I2S_DATAFORMAT_24B ((SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_0)) +#define I2S_DATAFORMAT_32B ((SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_1)) +/** + * @} + */ + +/** @defgroup I2S_MCLK_Output I2S MCLK Output + * @{ + */ +#define I2S_MCLKOUTPUT_ENABLE (SPI_I2SPR_MCKOE) +#define I2S_MCLKOUTPUT_DISABLE (0x00000000U) +/** + * @} + */ + +/** @defgroup I2S_Audio_Frequency I2S Audio Frequency + * @{ + */ +#define I2S_AUDIOFREQ_192K (192000U) +#define I2S_AUDIOFREQ_96K (96000U) +#define I2S_AUDIOFREQ_48K (48000U) +#define I2S_AUDIOFREQ_44K (44100U) +#define I2S_AUDIOFREQ_32K (32000U) +#define I2S_AUDIOFREQ_22K (22050U) +#define I2S_AUDIOFREQ_16K (16000U) +#define I2S_AUDIOFREQ_11K (11025U) +#define I2S_AUDIOFREQ_8K (8000U) +#define I2S_AUDIOFREQ_DEFAULT (2U) +/** + * @} + */ + +/** @defgroup I2S_FullDuplex_Mode I2S FullDuplex Mode + * @{ + */ +#define I2S_FULLDUPLEXMODE_DISABLE (0x00000000U) +#define I2S_FULLDUPLEXMODE_ENABLE (0x00000001U) +/** + * @} + */ + +/** @defgroup I2S_Clock_Polarity I2S Clock Polarity + * @{ + */ +#define I2S_CPOL_LOW (0x00000000U) +#define I2S_CPOL_HIGH (SPI_I2SCFGR_CKPOL) +/** + * @} + */ + +/** @defgroup I2S_Interrupts_Definition I2S Interrupts Definition + * @{ + */ +#define I2S_IT_TXE SPI_CR2_TXEIE +#define I2S_IT_RXNE SPI_CR2_RXNEIE +#define I2S_IT_ERR SPI_CR2_ERRIE +/** + * @} + */ + +/** @defgroup I2S_Flags_Definition I2S Flags Definition + * @{ + */ +#define I2S_FLAG_TXE SPI_SR_TXE +#define I2S_FLAG_RXNE SPI_SR_RXNE + +#define I2S_FLAG_UDR SPI_SR_UDR +#define I2S_FLAG_OVR SPI_SR_OVR +#define I2S_FLAG_FRE SPI_SR_FRE + +#define I2S_FLAG_CHSIDE SPI_SR_CHSIDE +#define I2S_FLAG_BSY SPI_SR_BSY + +#define I2S_FLAG_MASK (SPI_SR_RXNE\ + | SPI_SR_TXE | SPI_SR_UDR | SPI_SR_OVR | SPI_SR_FRE | SPI_SR_CHSIDE | SPI_SR_BSY) +/** + * @} + */ + +/** @defgroup I2S_Clock_Source I2S Clock Source Definition + * @{ + */ +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F469xx) || defined(STM32F479xx) +#define I2S_CLOCK_PLL (0x00000000U) +#define I2S_CLOCK_EXTERNAL (0x00000001U) +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || + STM32F401xC || STM32F401xE || STM32F411xE || STM32F469xx || STM32F479xx */ + +#if defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) +#define I2S_CLOCK_PLL (0x00000000U) +#define I2S_CLOCK_EXTERNAL (0x00000001U) +#define I2S_CLOCK_PLLR (0x00000002U) +#define I2S_CLOCK_PLLSRC (0x00000003U) +#endif /* STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ + +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +#define I2S_CLOCK_PLLSRC (0x00000000U) +#define I2S_CLOCK_EXTERNAL (0x00000001U) +#define I2S_CLOCK_PLLR (0x00000002U) +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup I2S_Exported_macros I2S Exported Macros + * @{ + */ + +/** @brief Reset I2S handle state + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) +#define __HAL_I2S_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_I2S_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_I2S_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_I2S_STATE_RESET) +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + +/** @brief Enable the specified SPI peripheral (in I2S mode). + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2S_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) + +/** @brief Disable the specified SPI peripheral (in I2S mode). + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2S_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) + +/** @brief Enable the specified I2S interrupts. + * @param __HANDLE__ specifies the I2S Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_I2S_ENABLE_IT(__HANDLE__, __INTERRUPT__) (SET_BIT((__HANDLE__)->Instance->CR2,(__INTERRUPT__))) + +/** @brief Disable the specified I2S interrupts. + * @param __HANDLE__ specifies the I2S Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_I2S_DISABLE_IT(__HANDLE__, __INTERRUPT__) (CLEAR_BIT((__HANDLE__)->Instance->CR2,(__INTERRUPT__))) + +/** @brief Checks if the specified I2S interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the I2S Handle. + * This parameter can be I2S where x: 1, 2, or 3 to select the I2S peripheral. + * @param __INTERRUPT__ specifies the I2S interrupt source to check. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_I2S_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified I2S flag is set or not. + * @param __HANDLE__ specifies the I2S Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2S_FLAG_RXNE: Receive buffer not empty flag + * @arg I2S_FLAG_TXE: Transmit buffer empty flag + * @arg I2S_FLAG_UDR: Underrun flag + * @arg I2S_FLAG_OVR: Overrun flag + * @arg I2S_FLAG_FRE: Frame error flag + * @arg I2S_FLAG_CHSIDE: Channel Side flag + * @arg I2S_FLAG_BSY: Busy flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_I2S_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) + +/** @brief Clears the I2S OVR pending flag. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2S_CLEAR_OVRFLAG(__HANDLE__) do{ \ + __IO uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = (__HANDLE__)->Instance->DR; \ + tmpreg_ovr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_ovr); \ + }while(0U) +/** @brief Clears the I2S UDR pending flag. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2S_CLEAR_UDRFLAG(__HANDLE__) do{\ + __IO uint32_t tmpreg_udr = 0x00U;\ + tmpreg_udr = ((__HANDLE__)->Instance->SR);\ + UNUSED(tmpreg_udr); \ + }while(0U) +/** @brief Flush the I2S DR Register. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2S_FLUSH_RX_DR(__HANDLE__) do{\ + __IO uint32_t tmpreg_dr = 0x00U;\ + tmpreg_dr = ((__HANDLE__)->Instance->DR);\ + UNUSED(tmpreg_dr); \ + }while(0U) +/** + * @} + */ + +/* Include I2S Extension module */ +#include "stm32f4xx_hal_i2s_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2S_Exported_Functions + * @{ + */ + +/** @addtogroup I2S_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s); +HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s); +void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s); +void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) +HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID, + pI2S_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_I2S_UnRegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup I2S_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ***************************************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size); +void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s); + +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size); + +HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s); +HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s); +HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s); + +/* Callbacks used in non blocking modes (Interrupt and DMA) *******************/ +void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s); +void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s); +void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s); +void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s); +void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s); +/** + * @} + */ + +/** @addtogroup I2S_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control and State functions ************************************/ +HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s); +uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2S_Private_Macros I2S Private Macros + * @{ + */ + +/** @brief Check whether the specified SPI flag is set or not. + * @param __SR__ copy of I2S SR register. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2S_FLAG_RXNE: Receive buffer not empty flag + * @arg I2S_FLAG_TXE: Transmit buffer empty flag + * @arg I2S_FLAG_UDR: Underrun error flag + * @arg I2S_FLAG_OVR: Overrun flag + * @arg I2S_FLAG_CHSIDE: Channel side flag + * @arg I2S_FLAG_BSY: Busy flag + * @retval SET or RESET. + */ +#define I2S_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__)\ + & ((__FLAG__) & I2S_FLAG_MASK)) == ((__FLAG__) & I2S_FLAG_MASK)) ? SET : RESET) + +/** @brief Check whether the specified SPI Interrupt is set or not. + * @param __CR2__ copy of I2S CR2 register. + * @param __INTERRUPT__ specifies the SPI interrupt source to check. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval SET or RESET. + */ +#define I2S_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__)\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks if I2S Mode parameter is in allowed range. + * @param __MODE__ specifies the I2S Mode. + * This parameter can be a value of @ref I2S_Mode + * @retval None + */ +#define IS_I2S_MODE(__MODE__) (((__MODE__) == I2S_MODE_SLAVE_TX) || \ + ((__MODE__) == I2S_MODE_SLAVE_RX) || \ + ((__MODE__) == I2S_MODE_MASTER_TX) || \ + ((__MODE__) == I2S_MODE_MASTER_RX)) + +#define IS_I2S_STANDARD(__STANDARD__) (((__STANDARD__) == I2S_STANDARD_PHILIPS) || \ + ((__STANDARD__) == I2S_STANDARD_MSB) || \ + ((__STANDARD__) == I2S_STANDARD_LSB) || \ + ((__STANDARD__) == I2S_STANDARD_PCM_SHORT) || \ + ((__STANDARD__) == I2S_STANDARD_PCM_LONG)) + +#define IS_I2S_DATA_FORMAT(__FORMAT__) (((__FORMAT__) == I2S_DATAFORMAT_16B) || \ + ((__FORMAT__) == I2S_DATAFORMAT_16B_EXTENDED) || \ + ((__FORMAT__) == I2S_DATAFORMAT_24B) || \ + ((__FORMAT__) == I2S_DATAFORMAT_32B)) + +#define IS_I2S_MCLK_OUTPUT(__OUTPUT__) (((__OUTPUT__) == I2S_MCLKOUTPUT_ENABLE) || \ + ((__OUTPUT__) == I2S_MCLKOUTPUT_DISABLE)) + +#define IS_I2S_AUDIO_FREQ(__FREQ__) ((((__FREQ__) >= I2S_AUDIOFREQ_8K) && \ + ((__FREQ__) <= I2S_AUDIOFREQ_192K)) || \ + ((__FREQ__) == I2S_AUDIOFREQ_DEFAULT)) + +#define IS_I2S_FULLDUPLEX_MODE(MODE) (((MODE) == I2S_FULLDUPLEXMODE_DISABLE) || \ + ((MODE) == I2S_FULLDUPLEXMODE_ENABLE)) + +/** @brief Checks if I2S Serial clock steady state parameter is in allowed range. + * @param __CPOL__ specifies the I2S serial clock steady state. + * This parameter can be a value of @ref I2S_Clock_Polarity + * @retval None + */ +#define IS_I2S_CPOL(__CPOL__) (((__CPOL__) == I2S_CPOL_LOW) || \ + ((__CPOL__) == I2S_CPOL_HIGH)) + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F469xx) || defined(STM32F479xx) +#define IS_I2S_CLOCKSOURCE(CLOCK) (((CLOCK) == I2S_CLOCK_EXTERNAL) ||\ + ((CLOCK) == I2S_CLOCK_PLL)) +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || + STM32F401xC || STM32F401xE || STM32F411xE || STM32F469xx || STM32F479xx */ + +#if defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined (STM32F413xx) || defined(STM32F423xx) +#define IS_I2S_CLOCKSOURCE(CLOCK) (((CLOCK) == I2S_CLOCK_EXTERNAL) ||\ + ((CLOCK) == I2S_CLOCK_PLL) ||\ + ((CLOCK) == I2S_CLOCK_PLLSRC) ||\ + ((CLOCK) == I2S_CLOCK_PLLR)) +#endif /* STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ + +#if defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) +#define IS_I2S_CLOCKSOURCE(CLOCK) (((CLOCK) == I2S_CLOCK_EXTERNAL) ||\ + ((CLOCK) == I2S_CLOCK_PLLSRC) ||\ + ((CLOCK) == I2S_CLOCK_PLLR)) +#endif /* STM32F410Tx || STM32F410Cx || STM32F410Rx */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_I2S_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h new file mode 100644 index 0000000..3aaa45b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2s_ex.h @@ -0,0 +1,183 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2s_ex.h + * @author MCD Application Team + * @brief Header file of I2S 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 STM32F4xx_HAL_I2S_EX_H +#define STM32F4xx_HAL_I2S_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined(SPI_I2S_FULLDUPLEX_SUPPORT) +/** @addtogroup I2SEx I2SEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup I2SEx_Exported_Macros I2S Extended Exported Macros + * @{ + */ + +#define I2SxEXT(__INSTANCE__) ((__INSTANCE__) == (SPI2)? (SPI_TypeDef *)(I2S2ext_BASE): (SPI_TypeDef *)(I2S3ext_BASE)) + +/** @brief Enable or disable the specified I2SExt peripheral. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2SEXT_ENABLE(__HANDLE__) (I2SxEXT((__HANDLE__)->Instance)->I2SCFGR |= SPI_I2SCFGR_I2SE) +#define __HAL_I2SEXT_DISABLE(__HANDLE__) (I2SxEXT((__HANDLE__)->Instance)->I2SCFGR &= ~SPI_I2SCFGR_I2SE) + +/** @brief Enable or disable the specified I2SExt interrupts. + * @param __HANDLE__ specifies the I2S Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_I2SEXT_ENABLE_IT(__HANDLE__, __INTERRUPT__) (I2SxEXT((__HANDLE__)->Instance)->CR2 |= (__INTERRUPT__)) +#define __HAL_I2SEXT_DISABLE_IT(__HANDLE__, __INTERRUPT__) (I2SxEXT((__HANDLE__)->Instance)->CR2 &= ~(__INTERRUPT__)) + +/** @brief Checks if the specified I2SExt interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the I2S Handle. + * This parameter can be I2S where x: 1, 2, or 3 to select the I2S peripheral. + * @param __INTERRUPT__ specifies the I2S interrupt source to check. + * This parameter can be one of the following values: + * @arg I2S_IT_TXE: Tx buffer empty interrupt enable + * @arg I2S_IT_RXNE: RX buffer not empty interrupt enable + * @arg I2S_IT_ERR: Error interrupt enable + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_I2SEXT_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((I2SxEXT((__HANDLE__)->Instance)->CR2\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified I2SExt flag is set or not. + * @param __HANDLE__ specifies the I2S Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg I2S_FLAG_RXNE: Receive buffer not empty flag + * @arg I2S_FLAG_TXE: Transmit buffer empty flag + * @arg I2S_FLAG_UDR: Underrun flag + * @arg I2S_FLAG_OVR: Overrun flag + * @arg I2S_FLAG_FRE: Frame error flag + * @arg I2S_FLAG_CHSIDE: Channel Side flag + * @arg I2S_FLAG_BSY: Busy flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_I2SEXT_GET_FLAG(__HANDLE__, __FLAG__) (((I2SxEXT((__HANDLE__)->Instance)->SR) & (__FLAG__)) == (__FLAG__)) + +/** @brief Clears the I2SExt OVR pending flag. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2SEXT_CLEAR_OVRFLAG(__HANDLE__) do{ \ + __IO uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = I2SxEXT((__HANDLE__)->Instance)->DR;\ + tmpreg_ovr = I2SxEXT((__HANDLE__)->Instance)->SR;\ + UNUSED(tmpreg_ovr); \ + }while(0U) +/** @brief Clears the I2SExt UDR pending flag. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2SEXT_CLEAR_UDRFLAG(__HANDLE__) do{ \ + __IO uint32_t tmpreg_udr = 0x00U; \ + tmpreg_udr = I2SxEXT((__HANDLE__)->Instance)->SR;\ + UNUSED(tmpreg_udr); \ + }while(0U) +/** @brief Flush the I2S and I2SExt DR Registers. + * @param __HANDLE__ specifies the I2S Handle. + * @retval None + */ +#define __HAL_I2SEXT_FLUSH_RX_DR(__HANDLE__) do{ \ + __IO uint32_t tmpreg_dr = 0x00U; \ + tmpreg_dr = I2SxEXT((__HANDLE__)->Instance)->DR; \ + tmpreg_dr = ((__HANDLE__)->Instance->DR); \ + UNUSED(tmpreg_dr); \ + }while(0U) +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2SEx_Exported_Functions I2S Extended Exported Functions + * @{ + */ + +/** @addtogroup I2SEx_Exported_Functions_Group1 I2S Extended IO operation functions + * @{ + */ + +/* Extended features functions *************************************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, + uint16_t Size, uint32_t Timeout); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, + uint16_t Size); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pTxData, uint16_t *pRxData, + uint16_t Size); +/* I2S IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_I2SEx_FullDuplex_IRQHandler(I2S_HandleTypeDef *hi2s); +void HAL_I2SEx_TxRxHalfCpltCallback(I2S_HandleTypeDef *hi2s); +void HAL_I2SEx_TxRxCpltCallback(I2S_HandleTypeDef *hi2s); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_I2S_EX_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h new file mode 100644 index 0000000..5735215 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_irda.h @@ -0,0 +1,682 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_irda.h + * @author MCD Application Team + * @brief Header file of IRDA 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 __STM32F4xx_HAL_IRDA_H +#define __STM32F4xx_HAL_IRDA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup IRDA + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup IRDA_Exported_Types IRDA Exported Types + * @{ + */ +/** + * @brief IRDA Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the IRDA communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (8 * (hirda->Init.BaudRate))) + - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8) + 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 IRDA_Word_Length */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref IRDA_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 IRDA_Mode */ + + uint8_t Prescaler; /*!< Specifies the Prescaler value to be programmed + in the IrDA low-power Baud Register, for defining pulse width on which + burst acceptance/rejection will be decided. This value is used as divisor + of system clock to achieve required pulse width. */ + + uint32_t IrDAMode; /*!< Specifies the IrDA mode + This parameter can be a value of @ref IRDA_Low_Power */ +} IRDA_InitTypeDef; + +/** + * @brief HAL IRDA State structures definition + * @note HAL IRDA State value is a combination of 2 different substates: gState and RxState. + * - gState contains IRDA 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 IP initialisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP initialized. HAL IRDA Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP 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 IP initialisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP 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_IRDA_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized + Value is allowed for gState and RxState */ + HAL_IRDA_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_IRDA_STATE_BUSY = 0x24U, /*!< An internal process is ongoing + Value is allowed for gState only */ + HAL_IRDA_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_IRDA_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_IRDA_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_IRDA_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_IRDA_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +} HAL_IRDA_StateTypeDef; + +/** + * @brief IRDA handle Structure definition + */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +typedef struct __IRDA_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ +{ + USART_TypeDef *Instance; /*!< USART registers base address */ + + IRDA_InitTypeDef Init; /*!< IRDA communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to IRDA Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< IRDA Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< IRDA Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to IRDA Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< IRDA Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< IRDA Rx Transfer Counter */ + + DMA_HandleTypeDef *hdmatx; /*!< IRDA Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< IRDA Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_IRDA_StateTypeDef gState; /*!< IRDA state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_IRDA_StateTypeDef */ + + __IO HAL_IRDA_StateTypeDef RxState; /*!< IRDA state information related to Rx operations. + This parameter can be a value of @ref HAL_IRDA_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< IRDA Error code */ + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + void (* TxHalfCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Tx Half Complete Callback */ + + void (* TxCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Tx Complete Callback */ + + void (* RxHalfCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Rx Half Complete Callback */ + + void (* RxCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Rx Complete Callback */ + + void (* ErrorCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Error Callback */ + + void (* AbortCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Abort Complete Callback */ + + void (* AbortTransmitCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Abort Transmit Complete Callback */ + + void (* AbortReceiveCpltCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Abort Receive Complete Callback */ + + + void (* MspInitCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Msp Init callback */ + + void (* MspDeInitCallback)(struct __IRDA_HandleTypeDef *hirda); /*!< IRDA Msp DeInit callback */ +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + +} IRDA_HandleTypeDef; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +/** + * @brief HAL IRDA Callback ID enumeration definition + */ +typedef enum +{ + HAL_IRDA_TX_HALFCOMPLETE_CB_ID = 0x00U, /*!< IRDA Tx Half Complete Callback ID */ + HAL_IRDA_TX_COMPLETE_CB_ID = 0x01U, /*!< IRDA Tx Complete Callback ID */ + HAL_IRDA_RX_HALFCOMPLETE_CB_ID = 0x02U, /*!< IRDA Rx Half Complete Callback ID */ + HAL_IRDA_RX_COMPLETE_CB_ID = 0x03U, /*!< IRDA Rx Complete Callback ID */ + HAL_IRDA_ERROR_CB_ID = 0x04U, /*!< IRDA Error Callback ID */ + HAL_IRDA_ABORT_COMPLETE_CB_ID = 0x05U, /*!< IRDA Abort Complete Callback ID */ + HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID = 0x06U, /*!< IRDA Abort Transmit Complete Callback ID */ + HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID = 0x07U, /*!< IRDA Abort Receive Complete Callback ID */ + + HAL_IRDA_MSPINIT_CB_ID = 0x08U, /*!< IRDA MspInit callback ID */ + HAL_IRDA_MSPDEINIT_CB_ID = 0x09U /*!< IRDA MspDeInit callback ID */ + +} HAL_IRDA_CallbackIDTypeDef; + +/** + * @brief HAL IRDA Callback pointer definition + */ +typedef void (*pIRDA_CallbackTypeDef)(IRDA_HandleTypeDef *hirda); /*!< pointer to an IRDA callback function */ + +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup IRDA_Exported_Constants IRDA Exported constants + * @{ + */ +/** @defgroup IRDA_Error_Code IRDA Error Code + * @{ + */ +#define HAL_IRDA_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_IRDA_ERROR_PE 0x00000001U /*!< Parity error */ +#define HAL_IRDA_ERROR_NE 0x00000002U /*!< Noise error */ +#define HAL_IRDA_ERROR_FE 0x00000004U /*!< Frame error */ +#define HAL_IRDA_ERROR_ORE 0x00000008U /*!< Overrun error */ +#define HAL_IRDA_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +#define HAL_IRDA_ERROR_INVALID_CALLBACK ((uint32_t)0x00000020U) /*!< Invalid Callback error */ +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup IRDA_Word_Length IRDA Word Length + * @{ + */ +#define IRDA_WORDLENGTH_8B 0x00000000U +#define IRDA_WORDLENGTH_9B ((uint32_t)USART_CR1_M) +/** + * @} + */ + +/** @defgroup IRDA_Parity IRDA Parity + * @{ + */ +#define IRDA_PARITY_NONE 0x00000000U +#define IRDA_PARITY_EVEN ((uint32_t)USART_CR1_PCE) +#define IRDA_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) +/** + * @} + */ + +/** @defgroup IRDA_Mode IRDA Transfer Mode + * @{ + */ +#define IRDA_MODE_RX ((uint32_t)USART_CR1_RE) +#define IRDA_MODE_TX ((uint32_t)USART_CR1_TE) +#define IRDA_MODE_TX_RX ((uint32_t)(USART_CR1_TE |USART_CR1_RE)) +/** + * @} + */ + +/** @defgroup IRDA_Low_Power IRDA Low Power + * @{ + */ +#define IRDA_POWERMODE_LOWPOWER ((uint32_t)USART_CR3_IRLP) +#define IRDA_POWERMODE_NORMAL 0x00000000U +/** + * @} + */ + +/** @defgroup IRDA_Flags IRDA Flags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the SR register + * @{ + */ +#define IRDA_FLAG_TXE ((uint32_t)USART_SR_TXE) +#define IRDA_FLAG_TC ((uint32_t)USART_SR_TC) +#define IRDA_FLAG_RXNE ((uint32_t)USART_SR_RXNE) +#define IRDA_FLAG_IDLE ((uint32_t)USART_SR_IDLE) +#define IRDA_FLAG_ORE ((uint32_t)USART_SR_ORE) +#define IRDA_FLAG_NE ((uint32_t)USART_SR_NE) +#define IRDA_FLAG_FE ((uint32_t)USART_SR_FE) +#define IRDA_FLAG_PE ((uint32_t)USART_SR_PE) +/** + * @} + */ + +/** @defgroup IRDA_Interrupt_definition IRDA Interrupt Definitions + * Elements values convention: 0xY000XXXX + * - XXXX : Interrupt mask in the XX register + * - Y : Interrupt source register (2bits) + * - 01: CR1 register + * - 10: CR2 register + * - 11: CR3 register + * @{ + */ +#define IRDA_IT_PE ((uint32_t)(IRDA_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) +#define IRDA_IT_TXE ((uint32_t)(IRDA_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) +#define IRDA_IT_TC ((uint32_t)(IRDA_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) +#define IRDA_IT_RXNE ((uint32_t)(IRDA_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) +#define IRDA_IT_IDLE ((uint32_t)(IRDA_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE)) + +#define IRDA_IT_LBD ((uint32_t)(IRDA_CR2_REG_INDEX << 28U | USART_CR2_LBDIE)) + +#define IRDA_IT_CTS ((uint32_t)(IRDA_CR3_REG_INDEX << 28U | USART_CR3_CTSIE)) +#define IRDA_IT_ERR ((uint32_t)(IRDA_CR3_REG_INDEX << 28U | USART_CR3_EIE)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup IRDA_Exported_Macros IRDA Exported Macros + * @{ + */ + +/** @brief Reset IRDA handle gstate & RxState + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1 +#define __HAL_IRDA_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_IRDA_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_IRDA_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_IRDA_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_IRDA_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_IRDA_STATE_RESET; \ + } while(0U) +#endif /*USE_HAL_IRDA_REGISTER_CALLBACKS */ + +/** @brief Flush the IRDA DR register + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR) + +/** @brief Check whether the specified IRDA flag is set or not. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA 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 IRDA_FLAG_TXE: Transmit data register empty flag + * @arg IRDA_FLAG_TC: Transmission Complete flag + * @arg IRDA_FLAG_RXNE: Receive data register not empty flag + * @arg IRDA_FLAG_IDLE: Idle Line detection flag + * @arg IRDA_FLAG_ORE: OverRun Error flag + * @arg IRDA_FLAG_NE: Noise Error flag + * @arg IRDA_FLAG_FE: Framing Error flag + * @arg IRDA_FLAG_PE: Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_IRDA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified IRDA pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA 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 IRDA_FLAG_TC: Transmission Complete flag. + * @arg IRDA_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_IRDA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Clear the IRDA PE pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR; \ + tmpreg = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg); \ + } while(0U) + +/** @brief Clear the IRDA FE pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_CLEAR_FEFLAG(__HANDLE__) __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the IRDA NE pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_CLEAR_NEFLAG(__HANDLE__) __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the IRDA ORE pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_CLEAR_OREFLAG(__HANDLE__) __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the IRDA IDLE pending flag. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_CLEAR_IDLEFLAG(__HANDLE__) __HAL_IRDA_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Enable the specified IRDA interrupt. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __INTERRUPT__ specifies the IRDA interrupt source to enable. + * This parameter can be one of the following values: + * @arg IRDA_IT_TXE: Transmit Data Register empty interrupt + * @arg IRDA_IT_TC: Transmission complete interrupt + * @arg IRDA_IT_RXNE: Receive Data register not empty interrupt + * @arg IRDA_IT_IDLE: Idle line detection interrupt + * @arg IRDA_IT_PE: Parity Error interrupt + * @arg IRDA_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_IRDA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == IRDA_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & IRDA_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == IRDA_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & IRDA_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & IRDA_IT_MASK))) +/** @brief Disable the specified IRDA interrupt. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __INTERRUPT__ specifies the IRDA interrupt source to disable. + * This parameter can be one of the following values: + * @arg IRDA_IT_TXE: Transmit Data Register empty interrupt + * @arg IRDA_IT_TC: Transmission complete interrupt + * @arg IRDA_IT_RXNE: Receive Data register not empty interrupt + * @arg IRDA_IT_IDLE: Idle line detection interrupt + * @arg IRDA_IT_PE: Parity Error interrupt + * @arg IRDA_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_IRDA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == IRDA_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & IRDA_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == IRDA_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 &= ~((__INTERRUPT__) & IRDA_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & IRDA_IT_MASK))) + +/** @brief Check whether the specified IRDA interrupt has occurred or not. + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @param __IT__ specifies the IRDA interrupt source to check. + * This parameter can be one of the following values: + * @arg IRDA_IT_TXE: Transmit Data Register empty interrupt + * @arg IRDA_IT_TC: Transmission complete interrupt + * @arg IRDA_IT_RXNE: Receive Data register not empty interrupt + * @arg IRDA_IT_IDLE: Idle line detection interrupt + * @arg IRDA_IT_ERR: Error interrupt + * @arg IRDA_IT_PE: Parity Error interrupt + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_IRDA_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == IRDA_CR1_REG_INDEX)? (__HANDLE__)->Instance->CR1:(((((uint32_t)(__IT__)) >> 28U) == IRDA_CR2_REG_INDEX)? \ + (__HANDLE__)->Instance->CR2 : (__HANDLE__)->Instance->CR3)) & (((uint32_t)(__IT__)) & IRDA_IT_MASK)) + +/** @brief Macro to enable the IRDA's one bit sample method + * @param __HANDLE__ specifies the IRDA Handle. + * @retval None + */ +#define __HAL_IRDA_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 |= USART_CR3_ONEBIT) + +/** @brief Macro to disable the IRDA's one bit sample method + * @param __HANDLE__ specifies the IRDA Handle. + * @retval None + */ +#define __HAL_IRDA_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 &= (uint16_t)~((uint16_t)USART_CR3_ONEBIT)) + +/** @brief Enable UART/USART associated to IRDA Handle + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_ENABLE(__HANDLE__) (SET_BIT((__HANDLE__)->Instance->CR1, USART_CR1_UE)) + +/** @brief Disable UART/USART associated to IRDA Handle + * @param __HANDLE__ specifies the IRDA Handle. + * IRDA Handle selects the USARTx or UARTy peripheral + * (USART,UART availability and x,y values depending on device). + * @retval None + */ +#define __HAL_IRDA_DISABLE(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, USART_CR1_UE)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup IRDA_Exported_Functions + * @{ + */ + +/** @addtogroup IRDA_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_IRDA_Init(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_DeInit(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_MspInit(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_MspDeInit(IRDA_HandleTypeDef *hirda); + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +/* Callbacks Register/UnRegister functions ***********************************/ +HAL_StatusTypeDef HAL_IRDA_RegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID, pIRDA_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_IRDA_UnRegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup IRDA_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef *hirda); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_IRDA_Abort(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_AbortTransmit(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_AbortReceive(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_Abort_IT(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_AbortTransmit_IT(IRDA_HandleTypeDef *hirda); +HAL_StatusTypeDef HAL_IRDA_AbortReceive_IT(IRDA_HandleTypeDef *hirda); + +void HAL_IRDA_IRQHandler(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_TxCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_RxCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_ErrorCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_AbortCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_AbortTransmitCpltCallback(IRDA_HandleTypeDef *hirda); +void HAL_IRDA_AbortReceiveCpltCallback(IRDA_HandleTypeDef *hirda); +/** + * @} + */ + +/** @addtogroup IRDA_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_IRDA_StateTypeDef HAL_IRDA_GetState(const IRDA_HandleTypeDef *hirda); +uint32_t HAL_IRDA_GetError(const IRDA_HandleTypeDef *hirda); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup IRDA_Private_Constants IRDA Private Constants + * @{ + */ + +/** @brief IRDA interruptions flag mask + * + */ +#define IRDA_IT_MASK ((uint32_t) USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | \ + USART_CR1_IDLEIE | USART_CR2_LBDIE | USART_CR3_CTSIE | USART_CR3_EIE ) + +#define IRDA_CR1_REG_INDEX 1U +#define IRDA_CR2_REG_INDEX 2U +#define IRDA_CR3_REG_INDEX 3U +/** + * @} + */ + +/* Private macros --------------------------------------------------------*/ +/** @defgroup IRDA_Private_Macros IRDA Private Macros + * @{ + */ +#define IS_IRDA_WORD_LENGTH(LENGTH) (((LENGTH) == IRDA_WORDLENGTH_8B) || \ + ((LENGTH) == IRDA_WORDLENGTH_9B)) + +#define IS_IRDA_PARITY(PARITY) (((PARITY) == IRDA_PARITY_NONE) || \ + ((PARITY) == IRDA_PARITY_EVEN) || \ + ((PARITY) == IRDA_PARITY_ODD)) + +#define IS_IRDA_MODE(MODE) ((((MODE) & 0x0000FFF3U) == 0x00U) && ((MODE) != 0x00000000U)) + +#define IS_IRDA_POWERMODE(MODE) (((MODE) == IRDA_POWERMODE_LOWPOWER) || \ + ((MODE) == IRDA_POWERMODE_NORMAL)) + +#define IS_IRDA_BAUDRATE(BAUDRATE) ((BAUDRATE) < 115201U) + +#define IRDA_DIV(_PCLK_, _BAUD_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(4U*(((uint64_t)(_BAUD_)))))) + +#define IRDA_DIVMANT(_PCLK_, _BAUD_) (IRDA_DIV((_PCLK_), (_BAUD_))/100U) + +#define IRDA_DIVFRAQ(_PCLK_, _BAUD_) ((((IRDA_DIV((_PCLK_), (_BAUD_)) - (IRDA_DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 16U) + 50U) / 100U) + +/* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + (UART DIVFRAQ & 0xF0) + (UART DIVFRAQ & 0x0FU) */ +#define IRDA_BRR(_PCLK_, _BAUD_) (((IRDA_DIVMANT((_PCLK_), (_BAUD_)) << 4U) + \ + (IRDA_DIVFRAQ((_PCLK_), (_BAUD_)) & 0xF0U)) + \ + (IRDA_DIVFRAQ((_PCLK_), (_BAUD_)) & 0x0FU)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup IRDA_Private_Functions IRDA Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_IRDA_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h new file mode 100644 index 0000000..5273730 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_iwdg.h @@ -0,0 +1,220 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_iwdg.h + * @author MCD Application Team + * @brief Header file of IWDG 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 STM32F4xx_HAL_IWDG_H +#define STM32F4xx_HAL_IWDG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup IWDG IWDG + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup IWDG_Exported_Types IWDG Exported Types + * @{ + */ + +/** + * @brief IWDG Init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Select the prescaler of the IWDG. + This parameter can be a value of @ref IWDG_Prescaler */ + + uint32_t Reload; /*!< Specifies the IWDG down-counter reload value. + This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */ + +} IWDG_InitTypeDef; + +/** + * @brief IWDG Handle Structure definition + */ +typedef struct +{ + IWDG_TypeDef *Instance; /*!< Register base address */ + + IWDG_InitTypeDef Init; /*!< IWDG required parameters */ +} IWDG_HandleTypeDef; + + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup IWDG_Exported_Constants IWDG Exported Constants + * @{ + */ + +/** @defgroup IWDG_Prescaler IWDG Prescaler + * @{ + */ +#define IWDG_PRESCALER_4 0x00000000u /*!< IWDG prescaler set to 4 */ +#define IWDG_PRESCALER_8 IWDG_PR_PR_0 /*!< IWDG prescaler set to 8 */ +#define IWDG_PRESCALER_16 IWDG_PR_PR_1 /*!< IWDG prescaler set to 16 */ +#define IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 32 */ +#define IWDG_PRESCALER_64 IWDG_PR_PR_2 /*!< IWDG prescaler set to 64 */ +#define IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 128 */ +#define IWDG_PRESCALER_256 (IWDG_PR_PR_2 | IWDG_PR_PR_1) /*!< IWDG prescaler set to 256 */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup IWDG_Exported_Macros IWDG Exported Macros + * @{ + */ + +/** + * @brief Enable the IWDG peripheral. + * @param __HANDLE__ IWDG handle + * @retval None + */ +#define __HAL_IWDG_START(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_ENABLE) + +/** + * @brief Reload IWDG counter with value defined in the reload register + * (write access to IWDG_PR and IWDG_RLR registers disabled). + * @param __HANDLE__ IWDG handle + * @retval None + */ +#define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup IWDG_Exported_Functions IWDG Exported Functions + * @{ + */ + +/** @defgroup IWDG_Exported_Functions_Group1 Initialization and Start functions + * @{ + */ +/* Initialization/Start functions ********************************************/ +HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg); +/** + * @} + */ + +/** @defgroup IWDG_Exported_Functions_Group2 IO operation functions + * @{ + */ +/* I/O operation functions ****************************************************/ +HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg); +/** + * @} + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup IWDG_Private_Constants IWDG Private Constants + * @{ + */ + +/** + * @brief IWDG Key Register BitMask + */ +#define IWDG_KEY_RELOAD 0x0000AAAAu /*!< IWDG Reload Counter Enable */ +#define IWDG_KEY_ENABLE 0x0000CCCCu /*!< IWDG Peripheral Enable */ +#define IWDG_KEY_WRITE_ACCESS_ENABLE 0x00005555u /*!< IWDG KR Write Access Enable */ +#define IWDG_KEY_WRITE_ACCESS_DISABLE 0x00000000u /*!< IWDG KR Write Access Disable */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup IWDG_Private_Macros IWDG Private Macros + * @{ + */ + +/** + * @brief Enable write access to IWDG_PR and IWDG_RLR registers. + * @param __HANDLE__ IWDG handle + * @retval None + */ +#define IWDG_ENABLE_WRITE_ACCESS(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_WRITE_ACCESS_ENABLE) + +/** + * @brief Disable write access to IWDG_PR and IWDG_RLR registers. + * @param __HANDLE__ IWDG handle + * @retval None + */ +#define IWDG_DISABLE_WRITE_ACCESS(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_WRITE_ACCESS_DISABLE) + +/** + * @brief Check IWDG prescaler value. + * @param __PRESCALER__ IWDG prescaler value + * @retval None + */ +#define IS_IWDG_PRESCALER(__PRESCALER__) (((__PRESCALER__) == IWDG_PRESCALER_4) || \ + ((__PRESCALER__) == IWDG_PRESCALER_8) || \ + ((__PRESCALER__) == IWDG_PRESCALER_16) || \ + ((__PRESCALER__) == IWDG_PRESCALER_32) || \ + ((__PRESCALER__) == IWDG_PRESCALER_64) || \ + ((__PRESCALER__) == IWDG_PRESCALER_128)|| \ + ((__PRESCALER__) == IWDG_PRESCALER_256)) + +/** + * @brief Check IWDG reload value. + * @param __RELOAD__ IWDG reload value + * @retval None + */ +#define IS_IWDG_RELOAD(__RELOAD__) ((__RELOAD__) <= IWDG_RLR_RL) + + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_IWDG_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h new file mode 100644 index 0000000..dd4b2ca --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_lptim.h @@ -0,0 +1,857 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_lptim.h + * @author MCD Application Team + * @brief Header file of LPTIM 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 STM32F4xx_HAL_LPTIM_H +#define STM32F4xx_HAL_LPTIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined (LPTIM1) + +/** @addtogroup LPTIM + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup LPTIM_Exported_Types LPTIM Exported Types + * @{ + */ +#define LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT EXTI_IMR_MR23 /*!< External interrupt line 23 Connected to the LPTIM EXTI Line */ + +/** + * @brief LPTIM Clock configuration definition + */ +typedef struct +{ + uint32_t Source; /*!< Selects the clock source. + This parameter can be a value of @ref LPTIM_Clock_Source */ + + uint32_t Prescaler; /*!< Specifies the counter clock Prescaler. + This parameter can be a value of @ref LPTIM_Clock_Prescaler */ + +} LPTIM_ClockConfigTypeDef; + +/** + * @brief LPTIM Clock configuration definition + */ +typedef struct +{ + uint32_t Polarity; /*!< Selects the polarity of the active edge for the counter unit + if the ULPTIM input is selected. + Note: This parameter is used only when Ultra low power clock source is used. + Note: If the polarity is configured on 'both edges', an auxiliary clock + (one of the Low power oscillator) must be active. + This parameter can be a value of @ref LPTIM_Clock_Polarity */ + + uint32_t SampleTime; /*!< Selects the clock sampling time to configure the clock glitch filter. + Note: This parameter is used only when Ultra low power clock source is used. + This parameter can be a value of @ref LPTIM_Clock_Sample_Time */ + +} LPTIM_ULPClockConfigTypeDef; + +/** + * @brief LPTIM Trigger configuration definition + */ +typedef struct +{ + uint32_t Source; /*!< Selects the Trigger source. + This parameter can be a value of @ref LPTIM_Trigger_Source */ + + uint32_t ActiveEdge; /*!< Selects the Trigger active edge. + Note: This parameter is used only when an external trigger is used. + This parameter can be a value of @ref LPTIM_External_Trigger_Polarity */ + + uint32_t SampleTime; /*!< Selects the trigger sampling time to configure the clock glitch filter. + Note: This parameter is used only when an external trigger is used. + This parameter can be a value of @ref LPTIM_Trigger_Sample_Time */ +} LPTIM_TriggerConfigTypeDef; + +/** + * @brief LPTIM Initialization Structure definition + */ +typedef struct +{ + LPTIM_ClockConfigTypeDef Clock; /*!< Specifies the clock parameters */ + + LPTIM_ULPClockConfigTypeDef UltraLowPowerClock;/*!< Specifies the Ultra Low Power clock parameters */ + + LPTIM_TriggerConfigTypeDef Trigger; /*!< Specifies the Trigger parameters */ + + uint32_t OutputPolarity; /*!< Specifies the Output polarity. + This parameter can be a value of @ref LPTIM_Output_Polarity */ + + uint32_t UpdateMode; /*!< Specifies whether the update of the autoreload and the compare + values is done immediately or after the end of current period. + This parameter can be a value of @ref LPTIM_Updating_Mode */ + + uint32_t CounterSource; /*!< Specifies whether the counter is incremented each internal event + or each external event. + This parameter can be a value of @ref LPTIM_Counter_Source */ +} LPTIM_InitTypeDef; + +/** + * @brief HAL LPTIM State structure definition + */ +typedef enum +{ + HAL_LPTIM_STATE_RESET = 0x00U, /*!< Peripheral not yet initialized or disabled */ + HAL_LPTIM_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_LPTIM_STATE_BUSY = 0x02U, /*!< An internal process is ongoing */ + HAL_LPTIM_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ + HAL_LPTIM_STATE_ERROR = 0x04U /*!< Internal Process is ongoing */ +} HAL_LPTIM_StateTypeDef; + +/** + * @brief LPTIM handle Structure definition + */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +typedef struct __LPTIM_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ +{ + LPTIM_TypeDef *Instance; /*!< Register base address */ + + LPTIM_InitTypeDef Init; /*!< LPTIM required parameters */ + + HAL_StatusTypeDef Status; /*!< LPTIM peripheral status */ + + HAL_LockTypeDef Lock; /*!< LPTIM locking object */ + + __IO HAL_LPTIM_StateTypeDef State; /*!< LPTIM peripheral state */ + +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< LPTIM Base Msp Init Callback */ + void (* MspDeInitCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< LPTIM Base Msp DeInit Callback */ + void (* CompareMatchCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Compare match Callback */ + void (* AutoReloadMatchCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Auto-reload match Callback */ + void (* TriggerCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< External trigger event detection Callback */ + void (* CompareWriteCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Compare register write complete Callback */ + void (* AutoReloadWriteCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Auto-reload register write complete Callback */ + void (* DirectionUpCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Up-counting direction change Callback */ + void (* DirectionDownCallback)(struct __LPTIM_HandleTypeDef *hlptim); /*!< Down-counting direction change Callback */ +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ +} LPTIM_HandleTypeDef; + +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +/** + * @brief HAL LPTIM Callback ID enumeration definition + */ +typedef enum +{ + HAL_LPTIM_MSPINIT_CB_ID = 0x00U, /*!< LPTIM Base Msp Init Callback ID */ + HAL_LPTIM_MSPDEINIT_CB_ID = 0x01U, /*!< LPTIM Base Msp DeInit Callback ID */ + HAL_LPTIM_COMPARE_MATCH_CB_ID = 0x02U, /*!< Compare match Callback ID */ + HAL_LPTIM_AUTORELOAD_MATCH_CB_ID = 0x03U, /*!< Auto-reload match Callback ID */ + HAL_LPTIM_TRIGGER_CB_ID = 0x04U, /*!< External trigger event detection Callback ID */ + HAL_LPTIM_COMPARE_WRITE_CB_ID = 0x05U, /*!< Compare register write complete Callback ID */ + HAL_LPTIM_AUTORELOAD_WRITE_CB_ID = 0x06U, /*!< Auto-reload register write complete Callback ID */ + HAL_LPTIM_DIRECTION_UP_CB_ID = 0x07U, /*!< Up-counting direction change Callback ID */ + HAL_LPTIM_DIRECTION_DOWN_CB_ID = 0x08U, /*!< Down-counting direction change Callback ID */ +} HAL_LPTIM_CallbackIDTypeDef; + +/** + * @brief HAL TIM Callback pointer definition + */ +typedef void (*pLPTIM_CallbackTypeDef)(LPTIM_HandleTypeDef *hlptim); /*!< pointer to the LPTIM callback function */ + +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup LPTIM_Exported_Constants LPTIM Exported Constants + * @{ + */ + +/** @defgroup LPTIM_Clock_Source LPTIM Clock Source + * @{ + */ +#define LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC 0x00000000U +#define LPTIM_CLOCKSOURCE_ULPTIM LPTIM_CFGR_CKSEL +/** + * @} + */ + +/** @defgroup LPTIM_Clock_Prescaler LPTIM Clock Prescaler + * @{ + */ +#define LPTIM_PRESCALER_DIV1 0x00000000U +#define LPTIM_PRESCALER_DIV2 LPTIM_CFGR_PRESC_0 +#define LPTIM_PRESCALER_DIV4 LPTIM_CFGR_PRESC_1 +#define LPTIM_PRESCALER_DIV8 (LPTIM_CFGR_PRESC_0 | LPTIM_CFGR_PRESC_1) +#define LPTIM_PRESCALER_DIV16 LPTIM_CFGR_PRESC_2 +#define LPTIM_PRESCALER_DIV32 (LPTIM_CFGR_PRESC_0 | LPTIM_CFGR_PRESC_2) +#define LPTIM_PRESCALER_DIV64 (LPTIM_CFGR_PRESC_1 | LPTIM_CFGR_PRESC_2) +#define LPTIM_PRESCALER_DIV128 LPTIM_CFGR_PRESC +/** + * @} + */ + +/** @defgroup LPTIM_Output_Polarity LPTIM Output Polarity + * @{ + */ + +#define LPTIM_OUTPUTPOLARITY_HIGH 0x00000000U +#define LPTIM_OUTPUTPOLARITY_LOW LPTIM_CFGR_WAVPOL +/** + * @} + */ + +/** @defgroup LPTIM_Clock_Sample_Time LPTIM Clock Sample Time + * @{ + */ +#define LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION 0x00000000U +#define LPTIM_CLOCKSAMPLETIME_2TRANSITIONS LPTIM_CFGR_CKFLT_0 +#define LPTIM_CLOCKSAMPLETIME_4TRANSITIONS LPTIM_CFGR_CKFLT_1 +#define LPTIM_CLOCKSAMPLETIME_8TRANSITIONS LPTIM_CFGR_CKFLT +/** + * @} + */ + +/** @defgroup LPTIM_Clock_Polarity LPTIM Clock Polarity + * @{ + */ +#define LPTIM_CLOCKPOLARITY_RISING 0x00000000U +#define LPTIM_CLOCKPOLARITY_FALLING LPTIM_CFGR_CKPOL_0 +#define LPTIM_CLOCKPOLARITY_RISING_FALLING LPTIM_CFGR_CKPOL_1 +/** + * @} + */ + +/** @defgroup LPTIM_Trigger_Source LPTIM Trigger Source + * @{ + */ +#define LPTIM_TRIGSOURCE_SOFTWARE 0x0000FFFFU +#define LPTIM_TRIGSOURCE_0 0x00000000U +#define LPTIM_TRIGSOURCE_1 LPTIM_CFGR_TRIGSEL_0 +#define LPTIM_TRIGSOURCE_2 LPTIM_CFGR_TRIGSEL_1 +#define LPTIM_TRIGSOURCE_3 (LPTIM_CFGR_TRIGSEL_0 | LPTIM_CFGR_TRIGSEL_1) +#define LPTIM_TRIGSOURCE_4 LPTIM_CFGR_TRIGSEL_2 +#define LPTIM_TRIGSOURCE_5 (LPTIM_CFGR_TRIGSEL_0 | LPTIM_CFGR_TRIGSEL_2) +/** + * @} + */ + +/** @defgroup LPTIM_External_Trigger_Polarity LPTIM External Trigger Polarity + * @{ + */ +#define LPTIM_ACTIVEEDGE_RISING LPTIM_CFGR_TRIGEN_0 +#define LPTIM_ACTIVEEDGE_FALLING LPTIM_CFGR_TRIGEN_1 +#define LPTIM_ACTIVEEDGE_RISING_FALLING LPTIM_CFGR_TRIGEN +/** + * @} + */ + +/** @defgroup LPTIM_Trigger_Sample_Time LPTIM Trigger Sample Time + * @{ + */ +#define LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION 0x00000000U +#define LPTIM_TRIGSAMPLETIME_2TRANSITIONS LPTIM_CFGR_TRGFLT_0 +#define LPTIM_TRIGSAMPLETIME_4TRANSITIONS LPTIM_CFGR_TRGFLT_1 +#define LPTIM_TRIGSAMPLETIME_8TRANSITIONS LPTIM_CFGR_TRGFLT +/** + * @} + */ + +/** @defgroup LPTIM_Updating_Mode LPTIM Updating Mode + * @{ + */ + +#define LPTIM_UPDATE_IMMEDIATE 0x00000000U +#define LPTIM_UPDATE_ENDOFPERIOD LPTIM_CFGR_PRELOAD +/** + * @} + */ + +/** @defgroup LPTIM_Counter_Source LPTIM Counter Source + * @{ + */ + +#define LPTIM_COUNTERSOURCE_INTERNAL 0x00000000U +#define LPTIM_COUNTERSOURCE_EXTERNAL LPTIM_CFGR_COUNTMODE +/** + * @} + */ + +/** @defgroup LPTIM_Flag_Definition LPTIM Flags Definition + * @{ + */ + +#define LPTIM_FLAG_DOWN LPTIM_ISR_DOWN +#define LPTIM_FLAG_UP LPTIM_ISR_UP +#define LPTIM_FLAG_ARROK LPTIM_ISR_ARROK +#define LPTIM_FLAG_CMPOK LPTIM_ISR_CMPOK +#define LPTIM_FLAG_EXTTRIG LPTIM_ISR_EXTTRIG +#define LPTIM_FLAG_ARRM LPTIM_ISR_ARRM +#define LPTIM_FLAG_CMPM LPTIM_ISR_CMPM +/** + * @} + */ + +/** @defgroup LPTIM_Interrupts_Definition LPTIM Interrupts Definition + * @{ + */ +#define LPTIM_IT_DOWN LPTIM_IER_DOWNIE +#define LPTIM_IT_UP LPTIM_IER_UPIE +#define LPTIM_IT_ARROK LPTIM_IER_ARROKIE +#define LPTIM_IT_CMPOK LPTIM_IER_CMPOKIE +#define LPTIM_IT_EXTTRIG LPTIM_IER_EXTTRIGIE +#define LPTIM_IT_ARRM LPTIM_IER_ARRMIE +#define LPTIM_IT_CMPM LPTIM_IER_CMPMIE +/** + * @} + */ + +/** @defgroup LPTIM_Option Register Definition + * @{ + */ +#define LPTIM_OP_PAD_AF 0x00000000U +#define LPTIM_OP_PAD_PA4 LPTIM_OR_LPT_IN1_RMP_0 +#define LPTIM_OP_PAD_PB9 LPTIM_OR_LPT_IN1_RMP_1 +#define LPTIM_OP_TIM_DAC LPTIM_OR_LPT_IN1_RMP +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup LPTIM_Exported_Macros LPTIM Exported Macros + * @{ + */ + +/** @brief Reset LPTIM handle state. + * @param __HANDLE__ LPTIM handle + * @retval None + */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +#define __HAL_LPTIM_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_LPTIM_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_LPTIM_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_LPTIM_STATE_RESET) +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + +/** + * @brief Enable the LPTIM peripheral. + * @param __HANDLE__ LPTIM handle + * @retval None + */ +#define __HAL_LPTIM_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (LPTIM_CR_ENABLE)) + +/** + * @brief Disable the LPTIM peripheral. + * @param __HANDLE__ LPTIM handle + * @note The following sequence is required to solve LPTIM disable HW limitation. + * Please check Errata Sheet ES0335 for more details under "MCU may remain + * stuck in LPTIM interrupt when entering Stop mode" section. + * @note Please call @ref HAL_LPTIM_GetState() after a call to __HAL_LPTIM_DISABLE to + * check for TIMEOUT. + * @retval None + */ +#define __HAL_LPTIM_DISABLE(__HANDLE__) LPTIM_Disable(__HANDLE__) + +/** + * @brief Start the LPTIM peripheral in Continuous mode. + * @param __HANDLE__ LPTIM handle + * @retval None + */ +#define __HAL_LPTIM_START_CONTINUOUS(__HANDLE__) ((__HANDLE__)->Instance->CR |= LPTIM_CR_CNTSTRT) +/** + * @brief Start the LPTIM peripheral in single mode. + * @param __HANDLE__ LPTIM handle + * @retval None + */ +#define __HAL_LPTIM_START_SINGLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= LPTIM_CR_SNGSTRT) + +/** + * @brief Write the passed parameter in the Autoreload register. + * @param __HANDLE__ LPTIM handle + * @param __VALUE__ Autoreload value + * @retval None + * @note The ARR register can only be modified when the LPTIM instance is enabled. + */ +#define __HAL_LPTIM_AUTORELOAD_SET(__HANDLE__ , __VALUE__) ((__HANDLE__)->Instance->ARR = (__VALUE__)) + +/** + * @brief Write the passed parameter in the Compare register. + * @param __HANDLE__ LPTIM handle + * @param __VALUE__ Compare value + * @retval None + * @note The CMP register can only be modified when the LPTIM instance is enabled. + */ +#define __HAL_LPTIM_COMPARE_SET(__HANDLE__ , __VALUE__) ((__HANDLE__)->Instance->CMP = (__VALUE__)) + +/** + * @brief Check whether the specified LPTIM flag is set or not. + * @param __HANDLE__ LPTIM handle + * @param __FLAG__ LPTIM flag to check + * This parameter can be a value of: + * @arg LPTIM_FLAG_DOWN : Counter direction change up Flag. + * @arg LPTIM_FLAG_UP : Counter direction change down to up Flag. + * @arg LPTIM_FLAG_ARROK : Autoreload register update OK Flag. + * @arg LPTIM_FLAG_CMPOK : Compare register update OK Flag. + * @arg LPTIM_FLAG_EXTTRIG : External trigger edge event Flag. + * @arg LPTIM_FLAG_ARRM : Autoreload match Flag. + * @arg LPTIM_FLAG_CMPM : Compare match Flag. + * @retval The state of the specified flag (SET or RESET). + */ +#define __HAL_LPTIM_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->ISR &(__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the specified LPTIM flag. + * @param __HANDLE__ LPTIM handle. + * @param __FLAG__ LPTIM flag to clear. + * This parameter can be a value of: + * @arg LPTIM_FLAG_DOWN : Counter direction change up Flag. + * @arg LPTIM_FLAG_UP : Counter direction change down to up Flag. + * @arg LPTIM_FLAG_ARROK : Autoreload register update OK Flag. + * @arg LPTIM_FLAG_CMPOK : Compare register update OK Flag. + * @arg LPTIM_FLAG_EXTTRIG : External trigger edge event Flag. + * @arg LPTIM_FLAG_ARRM : Autoreload match Flag. + * @arg LPTIM_FLAG_CMPM : Compare match Flag. + * @retval None. + */ +#define __HAL_LPTIM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__)) + +/** + * @brief Enable the specified LPTIM interrupt. + * @param __HANDLE__ LPTIM handle. + * @param __INTERRUPT__ LPTIM interrupt to set. + * This parameter can be a value of: + * @arg LPTIM_IT_DOWN : Counter direction change up Interrupt. + * @arg LPTIM_IT_UP : Counter direction change down to up Interrupt. + * @arg LPTIM_IT_ARROK : Autoreload register update OK Interrupt. + * @arg LPTIM_IT_CMPOK : Compare register update OK Interrupt. + * @arg LPTIM_IT_EXTTRIG : External trigger edge event Interrupt. + * @arg LPTIM_IT_ARRM : Autoreload match Interrupt. + * @arg LPTIM_IT_CMPM : Compare match Interrupt. + * @retval None. + * @note The LPTIM interrupts can only be enabled when the LPTIM instance is disabled. + */ +#define __HAL_LPTIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER |= (__INTERRUPT__)) + +/** + * @brief Disable the specified LPTIM interrupt. + * @param __HANDLE__ LPTIM handle. + * @param __INTERRUPT__ LPTIM interrupt to set. + * This parameter can be a value of: + * @arg LPTIM_IT_DOWN : Counter direction change up Interrupt. + * @arg LPTIM_IT_UP : Counter direction change down to up Interrupt. + * @arg LPTIM_IT_ARROK : Autoreload register update OK Interrupt. + * @arg LPTIM_IT_CMPOK : Compare register update OK Interrupt. + * @arg LPTIM_IT_EXTTRIG : External trigger edge event Interrupt. + * @arg LPTIM_IT_ARRM : Autoreload match Interrupt. + * @arg LPTIM_IT_CMPM : Compare match Interrupt. + * @retval None. + * @note The LPTIM interrupts can only be disabled when the LPTIM instance is disabled. + */ +#define __HAL_LPTIM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER &= (~(__INTERRUPT__))) + +/** + * @brief Check whether the specified LPTIM interrupt source is enabled or not. + * @param __HANDLE__ LPTIM handle. + * @param __INTERRUPT__ LPTIM interrupt to check. + * This parameter can be a value of: + * @arg LPTIM_IT_DOWN : Counter direction change up Interrupt. + * @arg LPTIM_IT_UP : Counter direction change down to up Interrupt. + * @arg LPTIM_IT_ARROK : Autoreload register update OK Interrupt. + * @arg LPTIM_IT_CMPOK : Compare register update OK Interrupt. + * @arg LPTIM_IT_EXTTRIG : External trigger edge event Interrupt. + * @arg LPTIM_IT_ARRM : Autoreload match Interrupt. + * @arg LPTIM_IT_CMPM : Compare match Interrupt. + * @retval Interrupt status. + */ + +#define __HAL_LPTIM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->IER\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief LPTIM Option Register + * @param __HANDLE__ LPTIM handle + * @param __VALUE__ This parameter can be a value of : + * @arg LPTIM_OP_PAD_AF + * @arg LPTIM_OP_PAD_PA4 + * @arg LPTIM_OP_PAD_PB9 + * @arg LPTIM_OP_TIM_DAC + * @retval None + */ +#define __HAL_LPTIM_OPTR_CONFIG(__HANDLE__ , __VALUE__) ((__HANDLE__)->Instance->OR = (__VALUE__)) + + +/** + * @brief Enable interrupt on the LPTIM Wake-up Timer associated Exti line. + * @retval None + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_IT() (EXTI->IMR\ + |= LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable interrupt on the LPTIM Wake-up Timer associated Exti line. + * @retval None + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_IT() (EXTI->IMR\ + &= ~(LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable event on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_EVENT() (EXTI->EMR\ + |= LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable event on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_EVENT() (EXTI->EMR\ + &= ~(LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT)) +#if defined(EXTI_IMR_MR23) + +/** + * @brief Enable falling edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR\ + |= LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable falling edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR\ + &= ~(LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR\ + |= LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable rising edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR\ + &= ~(LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT)) + +/** + * @brief Enable rising & falling edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_FALLING_EDGE() do{__HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();\ + __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE();\ + }while(0) + +/** + * @brief Disable rising & falling edge trigger on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_FALLING_EDGE() do{__HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE();\ + __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE();\ + }while(0) + +/** + * @brief Check whether the LPTIM Wake-up Timer associated Exti line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_GET_FLAG() (EXTI->PR\ + & LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Clear the LPTIM Wake-up Timer associated Exti line flag. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG() (EXTI->PR\ + = LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Generate a Software interrupt on the LPTIM Wake-up Timer associated Exti line. + * @retval None. + */ +#define __HAL_LPTIM_WAKEUPTIMER_EXTI_GENERATE_SWIT() (EXTI->SWIER\ + |= LPTIM_EXTI_LINE_WAKEUPTIMER_EVENT) +#endif /* EXTI_IMR_MR23 */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup LPTIM_Exported_Functions LPTIM Exported Functions + * @{ + */ + +/** @addtogroup LPTIM_Exported_Functions_Group1 + * @brief Initialization and Configuration functions. + * @{ + */ +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_LPTIM_Init(LPTIM_HandleTypeDef *hlptim); +HAL_StatusTypeDef HAL_LPTIM_DeInit(LPTIM_HandleTypeDef *hlptim); + +/* MSP functions *************************************************************/ +void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_MspDeInit(LPTIM_HandleTypeDef *hlptim); +/** + * @} + */ + +/** @addtogroup LPTIM_Exported_Functions_Group2 + * @brief Start-Stop operation functions. + * @{ + */ +/* Start/Stop operation functions *********************************************/ +/* ################################# PWM Mode ################################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_PWM_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_PWM_Stop_IT(LPTIM_HandleTypeDef *hlptim); + +/* ############################# One Pulse Mode ##############################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop_IT(LPTIM_HandleTypeDef *hlptim); + +/* ############################## Set once Mode ##############################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse); +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop_IT(LPTIM_HandleTypeDef *hlptim); + +/* ############################### Encoder Mode ##############################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period); +HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period); +HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop_IT(LPTIM_HandleTypeDef *hlptim); + +/* ############################# Time out Mode ##############################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout); +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout); +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop_IT(LPTIM_HandleTypeDef *hlptim); + +/* ############################## Counter Mode ###############################*/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period); +HAL_StatusTypeDef HAL_LPTIM_Counter_Stop(LPTIM_HandleTypeDef *hlptim); +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period); +HAL_StatusTypeDef HAL_LPTIM_Counter_Stop_IT(LPTIM_HandleTypeDef *hlptim); +/** + * @} + */ + +/** @addtogroup LPTIM_Exported_Functions_Group3 + * @brief Read operation functions. + * @{ + */ +/* Reading operation functions ************************************************/ +uint32_t HAL_LPTIM_ReadCounter(const LPTIM_HandleTypeDef *hlptim); +uint32_t HAL_LPTIM_ReadAutoReload(const LPTIM_HandleTypeDef *hlptim); +uint32_t HAL_LPTIM_ReadCompare(const LPTIM_HandleTypeDef *hlptim); +/** + * @} + */ + +/** @addtogroup LPTIM_Exported_Functions_Group4 + * @brief LPTIM IRQ handler and callback functions. + * @{ + */ +/* LPTIM IRQ functions *******************************************************/ +void HAL_LPTIM_IRQHandler(LPTIM_HandleTypeDef *hlptim); + +/* CallBack functions ********************************************************/ +void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_TriggerCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_CompareWriteCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_AutoReloadWriteCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_DirectionUpCallback(LPTIM_HandleTypeDef *hlptim); +void HAL_LPTIM_DirectionDownCallback(LPTIM_HandleTypeDef *hlptim); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_LPTIM_RegisterCallback(LPTIM_HandleTypeDef *lphtim, HAL_LPTIM_CallbackIDTypeDef CallbackID, + pLPTIM_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_LPTIM_UnRegisterCallback(LPTIM_HandleTypeDef *lphtim, HAL_LPTIM_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup LPTIM_Group5 + * @brief Peripheral State functions. + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_LPTIM_StateTypeDef HAL_LPTIM_GetState(LPTIM_HandleTypeDef *hlptim); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Types LPTIM Private Types + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Variables LPTIM Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Constants LPTIM Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Macros LPTIM Private Macros + * @{ + */ + +#define IS_LPTIM_CLOCK_SOURCE(__SOURCE__) (((__SOURCE__) == LPTIM_CLOCKSOURCE_ULPTIM) || \ + ((__SOURCE__) == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC)) + + +#define IS_LPTIM_CLOCK_PRESCALER(__PRESCALER__) (((__PRESCALER__) == LPTIM_PRESCALER_DIV1 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV2 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV4 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV8 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV16 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV32 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV64 ) || \ + ((__PRESCALER__) == LPTIM_PRESCALER_DIV128)) + +#define IS_LPTIM_CLOCK_PRESCALERDIV1(__PRESCALER__) ((__PRESCALER__) == LPTIM_PRESCALER_DIV1) + +#define IS_LPTIM_OUTPUT_POLARITY(__POLARITY__) (((__POLARITY__) == LPTIM_OUTPUTPOLARITY_LOW ) || \ + ((__POLARITY__) == LPTIM_OUTPUTPOLARITY_HIGH)) + +#define IS_LPTIM_CLOCK_SAMPLE_TIME(__SAMPLETIME__) (((__SAMPLETIME__) == LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION) || \ + ((__SAMPLETIME__) == LPTIM_CLOCKSAMPLETIME_2TRANSITIONS) || \ + ((__SAMPLETIME__) == LPTIM_CLOCKSAMPLETIME_4TRANSITIONS) || \ + ((__SAMPLETIME__) == LPTIM_CLOCKSAMPLETIME_8TRANSITIONS)) + +#define IS_LPTIM_CLOCK_POLARITY(__POLARITY__) (((__POLARITY__) == LPTIM_CLOCKPOLARITY_RISING) || \ + ((__POLARITY__) == LPTIM_CLOCKPOLARITY_FALLING) || \ + ((__POLARITY__) == LPTIM_CLOCKPOLARITY_RISING_FALLING)) + +#define IS_LPTIM_TRG_SOURCE(__TRIG__) (((__TRIG__) == LPTIM_TRIGSOURCE_SOFTWARE) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_0) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_1) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_2) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_3) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_4) || \ + ((__TRIG__) == LPTIM_TRIGSOURCE_5)) + +#define IS_LPTIM_EXT_TRG_POLARITY(__POLARITY__) (((__POLARITY__) == LPTIM_ACTIVEEDGE_RISING ) || \ + ((__POLARITY__) == LPTIM_ACTIVEEDGE_FALLING ) || \ + ((__POLARITY__) == LPTIM_ACTIVEEDGE_RISING_FALLING )) + +#define IS_LPTIM_TRIG_SAMPLE_TIME(__SAMPLETIME__) (((__SAMPLETIME__) == LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION) || \ + ((__SAMPLETIME__) == LPTIM_TRIGSAMPLETIME_2TRANSITIONS ) || \ + ((__SAMPLETIME__) == LPTIM_TRIGSAMPLETIME_4TRANSITIONS ) || \ + ((__SAMPLETIME__) == LPTIM_TRIGSAMPLETIME_8TRANSITIONS )) + +#define IS_LPTIM_UPDATE_MODE(__MODE__) (((__MODE__) == LPTIM_UPDATE_IMMEDIATE) || \ + ((__MODE__) == LPTIM_UPDATE_ENDOFPERIOD)) + +#define IS_LPTIM_COUNTER_SOURCE(__SOURCE__) (((__SOURCE__) == LPTIM_COUNTERSOURCE_INTERNAL) || \ + ((__SOURCE__) == LPTIM_COUNTERSOURCE_EXTERNAL)) + +#define IS_LPTIM_AUTORELOAD(__AUTORELOAD__) ((0x00000001UL <= (__AUTORELOAD__)) &&\ + ((__AUTORELOAD__) <= 0x0000FFFFUL)) + +#define IS_LPTIM_COMPARE(__COMPARE__) ((__COMPARE__) <= 0x0000FFFFUL) + +#define IS_LPTIM_PERIOD(__PERIOD__) ((0x00000001UL <= (__PERIOD__)) &&\ + ((__PERIOD__) <= 0x0000FFFFUL)) + +#define IS_LPTIM_PULSE(__PULSE__) ((__PULSE__) <= 0x0000FFFFUL) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Functions LPTIM Private Functions + * @{ + */ +void LPTIM_Disable(LPTIM_HandleTypeDef *hlptim); +/** + * @} + */ + +/** + * @} + */ + +#endif /* LPTIM1 */ +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_LPTIM_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h new file mode 100644 index 0000000..ab951d3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc.h @@ -0,0 +1,719 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_ltdc.h + * @author MCD Application Team + * @brief Header file of LTDC 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 STM32F4xx_HAL_LTDC_H +#define STM32F4xx_HAL_LTDC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined (LTDC) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup LTDC LTDC + * @brief LTDC HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup LTDC_Exported_Types LTDC Exported Types + * @{ + */ +#define MAX_LAYER 2U + +/** + * @brief LTDC color structure definition + */ +typedef struct +{ + uint8_t Blue; /*!< Configures the blue value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. */ + + uint8_t Green; /*!< Configures the green value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. */ + + uint8_t Red; /*!< Configures the red value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. */ + + uint8_t Reserved; /*!< Reserved 0xFF */ +} LTDC_ColorTypeDef; + +/** + * @brief LTDC Init structure definition + */ +typedef struct +{ + uint32_t HSPolarity; /*!< configures the horizontal synchronization polarity. + This parameter can be one value of @ref LTDC_HS_POLARITY */ + + uint32_t VSPolarity; /*!< configures the vertical synchronization polarity. + This parameter can be one value of @ref LTDC_VS_POLARITY */ + + uint32_t DEPolarity; /*!< configures the data enable polarity. + This parameter can be one of value of @ref LTDC_DE_POLARITY */ + + uint32_t PCPolarity; /*!< configures the pixel clock polarity. + This parameter can be one of value of @ref LTDC_PC_POLARITY */ + + uint32_t HorizontalSync; /*!< configures the number of Horizontal synchronization width. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0xFFF. */ + + uint32_t VerticalSync; /*!< configures the number of Vertical synchronization height. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0x7FF. */ + + uint32_t AccumulatedHBP; /*!< configures the accumulated horizontal back porch width. + This parameter must be a number between + Min_Data = LTDC_HorizontalSync and Max_Data = 0xFFF. */ + + uint32_t AccumulatedVBP; /*!< configures the accumulated vertical back porch height. + This parameter must be a number between + Min_Data = LTDC_VerticalSync and Max_Data = 0x7FF. */ + + uint32_t AccumulatedActiveW; /*!< configures the accumulated active width. + This parameter must be a number between + Min_Data = LTDC_AccumulatedHBP and Max_Data = 0xFFF. */ + + uint32_t AccumulatedActiveH; /*!< configures the accumulated active height. + This parameter must be a number between + Min_Data = LTDC_AccumulatedVBP and Max_Data = 0x7FF. */ + + uint32_t TotalWidth; /*!< configures the total width. + This parameter must be a number between + Min_Data = LTDC_AccumulatedActiveW and Max_Data = 0xFFF. */ + + uint32_t TotalHeigh; /*!< configures the total height. + This parameter must be a number between + Min_Data = LTDC_AccumulatedActiveH and Max_Data = 0x7FF. */ + + LTDC_ColorTypeDef Backcolor; /*!< Configures the background color. */ +} LTDC_InitTypeDef; + +/** + * @brief LTDC Layer structure definition + */ +typedef struct +{ + uint32_t WindowX0; /*!< Configures the Window Horizontal Start Position. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0xFFF. */ + + uint32_t WindowX1; /*!< Configures the Window Horizontal Stop Position. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0xFFF. */ + + uint32_t WindowY0; /*!< Configures the Window vertical Start Position. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0x7FF. */ + + uint32_t WindowY1; /*!< Configures the Window vertical Stop Position. + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0x7FF. */ + + uint32_t PixelFormat; /*!< Specifies the pixel format. + This parameter can be one of value of @ref LTDC_Pixelformat */ + + uint32_t Alpha; /*!< Specifies the constant alpha used for blending. + This parameter must be a number between + Min_Data = 0x00 and Max_Data = 0xFF. */ + + uint32_t Alpha0; /*!< Configures the default alpha value. + This parameter must be a number between + Min_Data = 0x00 and Max_Data = 0xFF. */ + + uint32_t BlendingFactor1; /*!< Select the blending factor 1. + This parameter can be one of value of @ref LTDC_BlendingFactor1 */ + + uint32_t BlendingFactor2; /*!< Select the blending factor 2. + This parameter can be one of value of @ref LTDC_BlendingFactor2 */ + + uint32_t FBStartAdress; /*!< Configures the color frame buffer address */ + + uint32_t ImageWidth; /*!< Configures the color frame buffer line length. + This parameter must be a number between + Min_Data = 0x0000 and Max_Data = 0x1FFF. */ + + uint32_t ImageHeight; /*!< Specifies the number of line in frame buffer. + This parameter must be a number between + Min_Data = 0x000 and Max_Data = 0x7FF. */ + + LTDC_ColorTypeDef Backcolor; /*!< Configures the layer background color. */ +} LTDC_LayerCfgTypeDef; + +/** + * @brief HAL LTDC State structures definition + */ +typedef enum +{ + HAL_LTDC_STATE_RESET = 0x00U, /*!< LTDC not yet initialized or disabled */ + HAL_LTDC_STATE_READY = 0x01U, /*!< LTDC initialized and ready for use */ + HAL_LTDC_STATE_BUSY = 0x02U, /*!< LTDC internal process is ongoing */ + HAL_LTDC_STATE_TIMEOUT = 0x03U, /*!< LTDC Timeout state */ + HAL_LTDC_STATE_ERROR = 0x04U /*!< LTDC state error */ +} HAL_LTDC_StateTypeDef; + +/** + * @brief LTDC handle Structure definition + */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +typedef struct __LTDC_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ +{ + LTDC_TypeDef *Instance; /*!< LTDC Register base address */ + + LTDC_InitTypeDef Init; /*!< LTDC parameters */ + + LTDC_LayerCfgTypeDef LayerCfg[MAX_LAYER]; /*!< LTDC Layers parameters */ + + HAL_LockTypeDef Lock; /*!< LTDC Lock */ + + __IO HAL_LTDC_StateTypeDef State; /*!< LTDC state */ + + __IO uint32_t ErrorCode; /*!< LTDC Error code */ + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + void (* LineEventCallback)(struct __LTDC_HandleTypeDef *hltdc); /*!< LTDC Line Event Callback */ + void (* ReloadEventCallback)(struct __LTDC_HandleTypeDef *hltdc); /*!< LTDC Reload Event Callback */ + void (* ErrorCallback)(struct __LTDC_HandleTypeDef *hltdc); /*!< LTDC Error Callback */ + + void (* MspInitCallback)(struct __LTDC_HandleTypeDef *hltdc); /*!< LTDC Msp Init callback */ + void (* MspDeInitCallback)(struct __LTDC_HandleTypeDef *hltdc); /*!< LTDC Msp DeInit callback */ + +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + + +} LTDC_HandleTypeDef; + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +/** + * @brief HAL LTDC Callback ID enumeration definition + */ +typedef enum +{ + HAL_LTDC_MSPINIT_CB_ID = 0x00U, /*!< LTDC MspInit callback ID */ + HAL_LTDC_MSPDEINIT_CB_ID = 0x01U, /*!< LTDC MspDeInit callback ID */ + + HAL_LTDC_LINE_EVENT_CB_ID = 0x02U, /*!< LTDC Line Event Callback ID */ + HAL_LTDC_RELOAD_EVENT_CB_ID = 0x03U, /*!< LTDC Reload Callback ID */ + HAL_LTDC_ERROR_CB_ID = 0x04U /*!< LTDC Error Callback ID */ + +} HAL_LTDC_CallbackIDTypeDef; + +/** + * @brief HAL LTDC Callback pointer definition + */ +typedef void (*pLTDC_CallbackTypeDef)(LTDC_HandleTypeDef *hltdc); /*!< pointer to an LTDC callback function */ + +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup LTDC_Exported_Constants LTDC Exported Constants + * @{ + */ + +/** @defgroup LTDC_Error_Code LTDC Error Code + * @{ + */ +#define HAL_LTDC_ERROR_NONE 0x00000000U /*!< LTDC No error */ +#define HAL_LTDC_ERROR_TE 0x00000001U /*!< LTDC Transfer error */ +#define HAL_LTDC_ERROR_FU 0x00000002U /*!< LTDC FIFO Underrun */ +#define HAL_LTDC_ERROR_TIMEOUT 0x00000020U /*!< LTDC Timeout error */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +#define HAL_LTDC_ERROR_INVALID_CALLBACK 0x00000040U /*!< LTDC Invalid Callback error */ +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup LTDC_Layer LTDC Layer + * @{ + */ +#define LTDC_LAYER_1 0x00000000U /*!< LTDC Layer 1 */ +#define LTDC_LAYER_2 0x00000001U /*!< LTDC Layer 2 */ +/** + * @} + */ + +/** @defgroup LTDC_HS_POLARITY LTDC HS POLARITY + * @{ + */ +#define LTDC_HSPOLARITY_AL 0x00000000U /*!< Horizontal Synchronization is active low. */ +#define LTDC_HSPOLARITY_AH LTDC_GCR_HSPOL /*!< Horizontal Synchronization is active high. */ +/** + * @} + */ + +/** @defgroup LTDC_VS_POLARITY LTDC VS POLARITY + * @{ + */ +#define LTDC_VSPOLARITY_AL 0x00000000U /*!< Vertical Synchronization is active low. */ +#define LTDC_VSPOLARITY_AH LTDC_GCR_VSPOL /*!< Vertical Synchronization is active high. */ +/** + * @} + */ + +/** @defgroup LTDC_DE_POLARITY LTDC DE POLARITY + * @{ + */ +#define LTDC_DEPOLARITY_AL 0x00000000U /*!< Data Enable, is active low. */ +#define LTDC_DEPOLARITY_AH LTDC_GCR_DEPOL /*!< Data Enable, is active high. */ +/** + * @} + */ + +/** @defgroup LTDC_PC_POLARITY LTDC PC POLARITY + * @{ + */ +#define LTDC_PCPOLARITY_IPC 0x00000000U /*!< input pixel clock. */ +#define LTDC_PCPOLARITY_IIPC LTDC_GCR_PCPOL /*!< inverted input pixel clock. */ +/** + * @} + */ + +/** @defgroup LTDC_SYNC LTDC SYNC + * @{ + */ +#define LTDC_HORIZONTALSYNC (LTDC_SSCR_HSW >> 16U) /*!< Horizontal synchronization width. */ +#define LTDC_VERTICALSYNC LTDC_SSCR_VSH /*!< Vertical synchronization height. */ +/** + * @} + */ + +/** @defgroup LTDC_BACK_COLOR LTDC BACK COLOR + * @{ + */ +#define LTDC_COLOR 0x000000FFU /*!< Color mask */ +/** + * @} + */ + +/** @defgroup LTDC_BlendingFactor1 LTDC Blending Factor1 + * @{ + */ +#define LTDC_BLENDING_FACTOR1_CA 0x00000400U /*!< Blending factor : Cte Alpha */ +#define LTDC_BLENDING_FACTOR1_PAxCA 0x00000600U /*!< Blending factor : Cte Alpha x Pixel Alpha*/ +/** + * @} + */ + +/** @defgroup LTDC_BlendingFactor2 LTDC Blending Factor2 + * @{ + */ +#define LTDC_BLENDING_FACTOR2_CA 0x00000005U /*!< Blending factor : Cte Alpha */ +#define LTDC_BLENDING_FACTOR2_PAxCA 0x00000007U /*!< Blending factor : Cte Alpha x Pixel Alpha*/ +/** + * @} + */ + +/** @defgroup LTDC_Pixelformat LTDC Pixel format + * @{ + */ +#define LTDC_PIXEL_FORMAT_ARGB8888 0x00000000U /*!< ARGB8888 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_RGB888 0x00000001U /*!< RGB888 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_RGB565 0x00000002U /*!< RGB565 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_ARGB1555 0x00000003U /*!< ARGB1555 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_ARGB4444 0x00000004U /*!< ARGB4444 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_L8 0x00000005U /*!< L8 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_AL44 0x00000006U /*!< AL44 LTDC pixel format */ +#define LTDC_PIXEL_FORMAT_AL88 0x00000007U /*!< AL88 LTDC pixel format */ +/** + * @} + */ + +/** @defgroup LTDC_Alpha LTDC Alpha + * @{ + */ +#define LTDC_ALPHA LTDC_LxCACR_CONSTA /*!< LTDC Constant Alpha mask */ +/** + * @} + */ + +/** @defgroup LTDC_LAYER_Config LTDC LAYER Config + * @{ + */ +#define LTDC_STOPPOSITION (LTDC_LxWHPCR_WHSPPOS >> 16U) /*!< LTDC Layer stop position */ +#define LTDC_STARTPOSITION LTDC_LxWHPCR_WHSTPOS /*!< LTDC Layer start position */ + +#define LTDC_COLOR_FRAME_BUFFER LTDC_LxCFBLR_CFBLL /*!< LTDC Layer Line length */ +#define LTDC_LINE_NUMBER LTDC_LxCFBLNR_CFBLNBR /*!< LTDC Layer Line number */ +/** + * @} + */ + +/** @defgroup LTDC_Interrupts LTDC Interrupts + * @{ + */ +#define LTDC_IT_LI LTDC_IER_LIE /*!< LTDC Line Interrupt */ +#define LTDC_IT_FU LTDC_IER_FUIE /*!< LTDC FIFO Underrun Interrupt */ +#define LTDC_IT_TE LTDC_IER_TERRIE /*!< LTDC Transfer Error Interrupt */ +#define LTDC_IT_RR LTDC_IER_RRIE /*!< LTDC Register Reload Interrupt */ +/** + * @} + */ + +/** @defgroup LTDC_Flags LTDC Flags + * @{ + */ +#define LTDC_FLAG_LI LTDC_ISR_LIF /*!< LTDC Line Interrupt Flag */ +#define LTDC_FLAG_FU LTDC_ISR_FUIF /*!< LTDC FIFO Underrun interrupt Flag */ +#define LTDC_FLAG_TE LTDC_ISR_TERRIF /*!< LTDC Transfer Error interrupt Flag */ +#define LTDC_FLAG_RR LTDC_ISR_RRIF /*!< LTDC Register Reload interrupt Flag */ +/** + * @} + */ + +/** @defgroup LTDC_Reload_Type LTDC Reload Type + * @{ + */ +#define LTDC_RELOAD_IMMEDIATE LTDC_SRCR_IMR /*!< Immediate Reload */ +#define LTDC_RELOAD_VERTICAL_BLANKING LTDC_SRCR_VBR /*!< Vertical Blanking Reload */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup LTDC_Exported_Macros LTDC Exported Macros + * @{ + */ + +/** @brief Reset LTDC handle state. + * @param __HANDLE__ LTDC handle + * @retval None + */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +#define __HAL_LTDC_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_LTDC_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_LTDC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_LTDC_STATE_RESET) +#endif /*USE_HAL_LTDC_REGISTER_CALLBACKS */ + +/** + * @brief Enable the LTDC. + * @param __HANDLE__ LTDC handle + * @retval None. + */ +#define __HAL_LTDC_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->GCR |= LTDC_GCR_LTDCEN) + +/** + * @brief Disable the LTDC. + * @param __HANDLE__ LTDC handle + * @retval None. + */ +#define __HAL_LTDC_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->GCR &= ~(LTDC_GCR_LTDCEN)) + +/** + * @brief Enable the LTDC Layer. + * @param __HANDLE__ LTDC handle + * @param __LAYER__ Specify the layer to be enabled. + * This parameter can be LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval None. + */ +#define __HAL_LTDC_LAYER_ENABLE(__HANDLE__, __LAYER__) ((LTDC_LAYER((__HANDLE__), (__LAYER__)))->CR\ + |= (uint32_t)LTDC_LxCR_LEN) + +/** + * @brief Disable the LTDC Layer. + * @param __HANDLE__ LTDC handle + * @param __LAYER__ Specify the layer to be disabled. + * This parameter can be LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval None. + */ +#define __HAL_LTDC_LAYER_DISABLE(__HANDLE__, __LAYER__) ((LTDC_LAYER((__HANDLE__), (__LAYER__)))->CR\ + &= ~(uint32_t)LTDC_LxCR_LEN) + +/** + * @brief Reload immediately all LTDC Layers. + * @param __HANDLE__ LTDC handle + * @retval None. + */ +#define __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG(__HANDLE__) ((__HANDLE__)->Instance->SRCR |= LTDC_SRCR_IMR) + +/** + * @brief Reload during vertical blanking period all LTDC Layers. + * @param __HANDLE__ LTDC handle + * @retval None. + */ +#define __HAL_LTDC_VERTICAL_BLANKING_RELOAD_CONFIG(__HANDLE__) ((__HANDLE__)->Instance->SRCR |= LTDC_SRCR_VBR) + +/* Interrupt & Flag management */ +/** + * @brief Get the LTDC pending flags. + * @param __HANDLE__ LTDC handle + * @param __FLAG__ Get the specified flag. + * This parameter can be any combination of the following values: + * @arg LTDC_FLAG_LI: Line Interrupt flag + * @arg LTDC_FLAG_FU: FIFO Underrun Interrupt flag + * @arg LTDC_FLAG_TE: Transfer Error interrupt flag + * @arg LTDC_FLAG_RR: Register Reload Interrupt Flag + * @retval The state of FLAG (SET or RESET). + */ +#define __HAL_LTDC_GET_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR & (__FLAG__)) + +/** + * @brief Clears the LTDC pending flags. + * @param __HANDLE__ LTDC handle + * @param __FLAG__ Specify the flag to clear. + * This parameter can be any combination of the following values: + * @arg LTDC_FLAG_LI: Line Interrupt flag + * @arg LTDC_FLAG_FU: FIFO Underrun Interrupt flag + * @arg LTDC_FLAG_TE: Transfer Error interrupt flag + * @arg LTDC_FLAG_RR: Register Reload Interrupt Flag + * @retval None + */ +#define __HAL_LTDC_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__)) + +/** + * @brief Enables the specified LTDC interrupts. + * @param __HANDLE__ LTDC handle + * @param __INTERRUPT__ Specify the LTDC interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg LTDC_IT_LI: Line Interrupt flag + * @arg LTDC_IT_FU: FIFO Underrun Interrupt flag + * @arg LTDC_IT_TE: Transfer Error interrupt flag + * @arg LTDC_IT_RR: Register Reload Interrupt Flag + * @retval None + */ +#define __HAL_LTDC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified LTDC interrupts. + * @param __HANDLE__ LTDC handle + * @param __INTERRUPT__ Specify the LTDC interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg LTDC_IT_LI: Line Interrupt flag + * @arg LTDC_IT_FU: FIFO Underrun Interrupt flag + * @arg LTDC_IT_TE: Transfer Error interrupt flag + * @arg LTDC_IT_RR: Register Reload Interrupt Flag + * @retval None + */ +#define __HAL_LTDC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified LTDC interrupt has occurred or not. + * @param __HANDLE__ LTDC handle + * @param __INTERRUPT__ Specify the LTDC interrupt source to check. + * This parameter can be one of the following values: + * @arg LTDC_IT_LI: Line Interrupt flag + * @arg LTDC_IT_FU: FIFO Underrun Interrupt flag + * @arg LTDC_IT_TE: Transfer Error interrupt flag + * @arg LTDC_IT_RR: Register Reload Interrupt Flag + * @retval The state of INTERRUPT (SET or RESET). + */ +#define __HAL_LTDC_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IER & (__INTERRUPT__)) +/** + * @} + */ + +/* Include LTDC HAL Extension module */ +#include "stm32f4xx_hal_ltdc_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup LTDC_Exported_Functions + * @{ + */ +/** @addtogroup LTDC_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions *****************************/ +HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc); +HAL_StatusTypeDef HAL_LTDC_DeInit(LTDC_HandleTypeDef *hltdc); +void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc); +void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc); +void HAL_LTDC_ErrorCallback(LTDC_HandleTypeDef *hltdc); +void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc); +void HAL_LTDC_ReloadEventCallback(LTDC_HandleTypeDef *hltdc); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_LTDC_RegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID, + pLTDC_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_LTDC_UnRegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup LTDC_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *****************************************************/ +void HAL_LTDC_IRQHandler(LTDC_HandleTypeDef *hltdc); +/** + * @} + */ + +/** @addtogroup LTDC_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions ***********************************************/ +HAL_StatusTypeDef HAL_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetWindowSize(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetWindowPosition(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetPixelFormat(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetAlpha(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetAddress(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetPitch(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_ConfigCLUT(LTDC_HandleTypeDef *hltdc, uint32_t *pCLUT, uint32_t CLUTSize, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_EnableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_DisableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_EnableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_DisableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_ProgramLineEvent(LTDC_HandleTypeDef *hltdc, uint32_t Line); +HAL_StatusTypeDef HAL_LTDC_EnableDither(LTDC_HandleTypeDef *hltdc); +HAL_StatusTypeDef HAL_LTDC_DisableDither(LTDC_HandleTypeDef *hltdc); +HAL_StatusTypeDef HAL_LTDC_Reload(LTDC_HandleTypeDef *hltdc, uint32_t ReloadType); +HAL_StatusTypeDef HAL_LTDC_ConfigLayer_NoReload(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, + uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetWindowSize_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, + uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetWindowPosition_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, + uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetPixelFormat_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetAlpha_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetAddress_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_SetPitch_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_EnableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_DisableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_EnableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); +HAL_StatusTypeDef HAL_LTDC_DisableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx); + +/** + * @} + */ + +/** @addtogroup LTDC_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions *************************************************/ +HAL_LTDC_StateTypeDef HAL_LTDC_GetState(LTDC_HandleTypeDef *hltdc); +uint32_t HAL_LTDC_GetError(LTDC_HandleTypeDef *hltdc); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup LTDC_Private_Macros LTDC Private Macros + * @{ + */ +#define LTDC_LAYER(__HANDLE__, __LAYER__) ((LTDC_Layer_TypeDef *)((uint32_t)(\ + ((uint32_t)((__HANDLE__)->Instance))\ + + 0x84U + (0x80U*(__LAYER__))))) +#define IS_LTDC_LAYER(__LAYER__) ((__LAYER__) < MAX_LAYER) +#define IS_LTDC_HSPOL(__HSPOL__) (((__HSPOL__) == LTDC_HSPOLARITY_AL)\ + || ((__HSPOL__) == LTDC_HSPOLARITY_AH)) +#define IS_LTDC_VSPOL(__VSPOL__) (((__VSPOL__) == LTDC_VSPOLARITY_AL)\ + || ((__VSPOL__) == LTDC_VSPOLARITY_AH)) +#define IS_LTDC_DEPOL(__DEPOL__) (((__DEPOL__) == LTDC_DEPOLARITY_AL)\ + || ((__DEPOL__) == LTDC_DEPOLARITY_AH)) +#define IS_LTDC_PCPOL(__PCPOL__) (((__PCPOL__) == LTDC_PCPOLARITY_IPC)\ + || ((__PCPOL__) == LTDC_PCPOLARITY_IIPC)) +#define IS_LTDC_HSYNC(__HSYNC__) ((__HSYNC__) <= LTDC_HORIZONTALSYNC) +#define IS_LTDC_VSYNC(__VSYNC__) ((__VSYNC__) <= LTDC_VERTICALSYNC) +#define IS_LTDC_AHBP(__AHBP__) ((__AHBP__) <= LTDC_HORIZONTALSYNC) +#define IS_LTDC_AVBP(__AVBP__) ((__AVBP__) <= LTDC_VERTICALSYNC) +#define IS_LTDC_AAW(__AAW__) ((__AAW__) <= LTDC_HORIZONTALSYNC) +#define IS_LTDC_AAH(__AAH__) ((__AAH__) <= LTDC_VERTICALSYNC) +#define IS_LTDC_TOTALW(__TOTALW__) ((__TOTALW__) <= LTDC_HORIZONTALSYNC) +#define IS_LTDC_TOTALH(__TOTALH__) ((__TOTALH__) <= LTDC_VERTICALSYNC) +#define IS_LTDC_BLUEVALUE(__BBLUE__) ((__BBLUE__) <= LTDC_COLOR) +#define IS_LTDC_GREENVALUE(__BGREEN__) ((__BGREEN__) <= LTDC_COLOR) +#define IS_LTDC_REDVALUE(__BRED__) ((__BRED__) <= LTDC_COLOR) +#define IS_LTDC_BLENDING_FACTOR1(__BLENDING_FACTOR1__) (((__BLENDING_FACTOR1__) == LTDC_BLENDING_FACTOR1_CA) || \ + ((__BLENDING_FACTOR1__) == LTDC_BLENDING_FACTOR1_PAxCA)) +#define IS_LTDC_BLENDING_FACTOR2(__BLENDING_FACTOR1__) (((__BLENDING_FACTOR1__) == LTDC_BLENDING_FACTOR2_CA) || \ + ((__BLENDING_FACTOR1__) == LTDC_BLENDING_FACTOR2_PAxCA)) +#define IS_LTDC_PIXEL_FORMAT(__PIXEL_FORMAT__) (((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_ARGB8888) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_RGB888) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_RGB565) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_ARGB1555) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_ARGB4444) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_L8) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_AL44) || \ + ((__PIXEL_FORMAT__) == LTDC_PIXEL_FORMAT_AL88)) +#define IS_LTDC_ALPHA(__ALPHA__) ((__ALPHA__) <= LTDC_ALPHA) +#define IS_LTDC_HCONFIGST(__HCONFIGST__) ((__HCONFIGST__) <= LTDC_STARTPOSITION) +#define IS_LTDC_HCONFIGSP(__HCONFIGSP__) ((__HCONFIGSP__) <= LTDC_STOPPOSITION) +#define IS_LTDC_VCONFIGST(__VCONFIGST__) ((__VCONFIGST__) <= LTDC_STARTPOSITION) +#define IS_LTDC_VCONFIGSP(__VCONFIGSP__) ((__VCONFIGSP__) <= LTDC_STOPPOSITION) +#define IS_LTDC_CFBP(__CFBP__) ((__CFBP__) <= LTDC_COLOR_FRAME_BUFFER) +#define IS_LTDC_CFBLL(__CFBLL__) ((__CFBLL__) <= LTDC_COLOR_FRAME_BUFFER) +#define IS_LTDC_CFBLNBR(__CFBLNBR__) ((__CFBLNBR__) <= LTDC_LINE_NUMBER) +#define IS_LTDC_LIPOS(__LIPOS__) ((__LIPOS__) <= 0x7FFU) +#define IS_LTDC_RELOAD(__RELOADTYPE__) (((__RELOADTYPE__) == LTDC_RELOAD_IMMEDIATE) || \ + ((__RELOADTYPE__) == LTDC_RELOAD_VERTICAL_BLANKING)) +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup LTDC_Private_Functions LTDC Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* LTDC */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_LTDC_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h new file mode 100644 index 0000000..b9c39e4 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_ltdc_ex.h @@ -0,0 +1,83 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_ltdc_ex.h + * @author MCD Application Team + * @brief Header file of LTDC HAL Extension 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 STM32F4xx_HAL_LTDC_EX_H +#define STM32F4xx_HAL_LTDC_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined (LTDC) && defined (DSI) + +#include "stm32f4xx_hal_dsi.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup LTDCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup LTDCEx_Exported_Functions + * @{ + */ + +/** @addtogroup LTDCEx_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_LTDCEx_StructInitFromVideoConfig(LTDC_HandleTypeDef *hltdc, DSI_VidCfgTypeDef *VidCfg); +HAL_StatusTypeDef HAL_LTDCEx_StructInitFromAdaptedCommandConfig(LTDC_HandleTypeDef *hltdc, DSI_CmdCfgTypeDef *CmdCfg); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* LTDC && DSI */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_LTDC_EX_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h new file mode 100644 index 0000000..30921aa --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_mmc.h @@ -0,0 +1,747 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_mmc.h + * @author MCD Application Team + * @brief Header file of MMC 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 STM32F4xx_HAL_MMC_H +#define STM32F4xx_HAL_MMC_H + +#if defined(SDIO) + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_sdmmc.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup MMC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup MMC_Exported_Types MMC Exported Types + * @{ + */ + +/** @defgroup MMC_Exported_Types_Group1 MMC State enumeration structure + * @{ + */ +typedef enum +{ + HAL_MMC_STATE_RESET = 0x00000000U, /*!< MMC not yet initialized or disabled */ + HAL_MMC_STATE_READY = 0x00000001U, /*!< MMC initialized and ready for use */ + HAL_MMC_STATE_TIMEOUT = 0x00000002U, /*!< MMC Timeout state */ + HAL_MMC_STATE_BUSY = 0x00000003U, /*!< MMC process ongoing */ + HAL_MMC_STATE_PROGRAMMING = 0x00000004U, /*!< MMC Programming State */ + HAL_MMC_STATE_RECEIVING = 0x00000005U, /*!< MMC Receinving State */ + HAL_MMC_STATE_TRANSFER = 0x00000006U, /*!< MMC Transfer State */ + HAL_MMC_STATE_ERROR = 0x0000000FU /*!< MMC is in error state */ +}HAL_MMC_StateTypeDef; +/** + * @} + */ + +/** @defgroup MMC_Exported_Types_Group2 MMC Card State enumeration structure + * @{ + */ +typedef uint32_t HAL_MMC_CardStateTypeDef; + +#define HAL_MMC_CARD_READY 0x00000001U /*!< Card state is ready */ +#define HAL_MMC_CARD_IDENTIFICATION 0x00000002U /*!< Card is in identification state */ +#define HAL_MMC_CARD_STANDBY 0x00000003U /*!< Card is in standby state */ +#define HAL_MMC_CARD_TRANSFER 0x00000004U /*!< Card is in transfer state */ +#define HAL_MMC_CARD_SENDING 0x00000005U /*!< Card is sending an operation */ +#define HAL_MMC_CARD_RECEIVING 0x00000006U /*!< Card is receiving operation information */ +#define HAL_MMC_CARD_PROGRAMMING 0x00000007U /*!< Card is in programming state */ +#define HAL_MMC_CARD_DISCONNECTED 0x00000008U /*!< Card is disconnected */ +#define HAL_MMC_CARD_ERROR 0x000000FFU /*!< Card response Error */ +/** + * @} + */ + +/** @defgroup MMC_Exported_Types_Group3 MMC Handle Structure definition + * @{ + */ +#define MMC_InitTypeDef SDIO_InitTypeDef +#define MMC_TypeDef SDIO_TypeDef + +/** + * @brief MMC Card Information Structure definition + */ +typedef struct +{ + uint32_t CardType; /*!< Specifies the card Type */ + + uint32_t Class; /*!< Specifies the class of the card class */ + + uint32_t RelCardAdd; /*!< Specifies the Relative Card Address */ + + uint32_t BlockNbr; /*!< Specifies the Card Capacity in blocks */ + + uint32_t BlockSize; /*!< Specifies one block size in bytes */ + + uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ + + uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ + +}HAL_MMC_CardInfoTypeDef; + +/** + * @brief MMC handle Structure definition + */ +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +typedef struct __MMC_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ +{ + MMC_TypeDef *Instance; /*!< MMC registers base address */ + + MMC_InitTypeDef Init; /*!< MMC required parameters */ + + HAL_LockTypeDef Lock; /*!< MMC locking object */ + + uint8_t *pTxBuffPtr; /*!< Pointer to MMC Tx transfer Buffer */ + + uint32_t TxXferSize; /*!< MMC Tx Transfer size */ + + uint8_t *pRxBuffPtr; /*!< Pointer to MMC Rx transfer Buffer */ + + uint32_t RxXferSize; /*!< MMC Rx Transfer size */ + + __IO uint32_t Context; /*!< MMC transfer context */ + + __IO HAL_MMC_StateTypeDef State; /*!< MMC card State */ + + __IO uint32_t ErrorCode; /*!< MMC Card Error codes */ + + DMA_HandleTypeDef *hdmarx; /*!< MMC Rx DMA handle parameters */ + + DMA_HandleTypeDef *hdmatx; /*!< MMC Tx DMA handle parameters */ + + HAL_MMC_CardInfoTypeDef MmcCard; /*!< MMC Card information */ + + uint32_t CSD[4U]; /*!< MMC card specific data table */ + + uint32_t CID[4U]; /*!< MMC card identification number table */ + + uint32_t Ext_CSD[128]; + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + void (* TxCpltCallback) (struct __MMC_HandleTypeDef *hmmc); + void (* RxCpltCallback) (struct __MMC_HandleTypeDef *hmmc); + void (* ErrorCallback) (struct __MMC_HandleTypeDef *hmmc); + void (* AbortCpltCallback) (struct __MMC_HandleTypeDef *hmmc); + + void (* MspInitCallback) (struct __MMC_HandleTypeDef *hmmc); + void (* MspDeInitCallback) (struct __MMC_HandleTypeDef *hmmc); +#endif +}MMC_HandleTypeDef; + +/** + * @} + */ + +/** @defgroup MMC_Exported_Types_Group4 Card Specific Data: CSD Register + * @{ + */ +typedef struct +{ + __IO uint8_t CSDStruct; /*!< CSD structure */ + __IO uint8_t SysSpecVersion; /*!< System specification version */ + __IO uint8_t Reserved1; /*!< Reserved */ + __IO uint8_t TAAC; /*!< Data read access time 1 */ + __IO uint8_t NSAC; /*!< Data read access time 2 in CLK cycles */ + __IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */ + __IO uint16_t CardComdClasses; /*!< Card command classes */ + __IO uint8_t RdBlockLen; /*!< Max. read data block length */ + __IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */ + __IO uint8_t WrBlockMisalign; /*!< Write block misalignment */ + __IO uint8_t RdBlockMisalign; /*!< Read block misalignment */ + __IO uint8_t DSRImpl; /*!< DSR implemented */ + __IO uint8_t Reserved2; /*!< Reserved */ + __IO uint32_t DeviceSize; /*!< Device Size */ + __IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */ + __IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */ + __IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */ + __IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */ + __IO uint8_t DeviceSizeMul; /*!< Device size multiplier */ + __IO uint8_t EraseGrSize; /*!< Erase group size */ + __IO uint8_t EraseGrMul; /*!< Erase group size multiplier */ + __IO uint8_t WrProtectGrSize; /*!< Write protect group size */ + __IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */ + __IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */ + __IO uint8_t WrSpeedFact; /*!< Write speed factor */ + __IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */ + __IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */ + __IO uint8_t Reserved3; /*!< Reserved */ + __IO uint8_t ContentProtectAppli; /*!< Content protection application */ + __IO uint8_t FileFormatGroup; /*!< File format group */ + __IO uint8_t CopyFlag; /*!< Copy flag (OTP) */ + __IO uint8_t PermWrProtect; /*!< Permanent write protection */ + __IO uint8_t TempWrProtect; /*!< Temporary write protection */ + __IO uint8_t FileFormat; /*!< File format */ + __IO uint8_t ECC; /*!< ECC code */ + __IO uint8_t CSD_CRC; /*!< CSD CRC */ + __IO uint8_t Reserved4; /*!< Always 1 */ + +}HAL_MMC_CardCSDTypeDef; +/** + * @} + */ + +/** @defgroup MMC_Exported_Types_Group5 Card Identification Data: CID Register + * @{ + */ +typedef struct +{ + __IO uint8_t ManufacturerID; /*!< Manufacturer ID */ + __IO uint16_t OEM_AppliID; /*!< OEM/Application ID */ + __IO uint32_t ProdName1; /*!< Product Name part1 */ + __IO uint8_t ProdName2; /*!< Product Name part2 */ + __IO uint8_t ProdRev; /*!< Product Revision */ + __IO uint32_t ProdSN; /*!< Product Serial Number */ + __IO uint8_t Reserved1; /*!< Reserved1 */ + __IO uint16_t ManufactDate; /*!< Manufacturing Date */ + __IO uint8_t CID_CRC; /*!< CID CRC */ + __IO uint8_t Reserved2; /*!< Always 1 */ + +}HAL_MMC_CardCIDTypeDef; +/** + * @} + */ + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +/** @defgroup MMC_Exported_Types_Group6 MMC Callback ID enumeration definition + * @{ + */ +typedef enum +{ + HAL_MMC_TX_CPLT_CB_ID = 0x00U, /*!< MMC Tx Complete Callback ID */ + HAL_MMC_RX_CPLT_CB_ID = 0x01U, /*!< MMC Rx Complete Callback ID */ + HAL_MMC_ERROR_CB_ID = 0x02U, /*!< MMC Error Callback ID */ + HAL_MMC_ABORT_CB_ID = 0x03U, /*!< MMC Abort Callback ID */ + + HAL_MMC_MSP_INIT_CB_ID = 0x10U, /*!< MMC MspInit Callback ID */ + HAL_MMC_MSP_DEINIT_CB_ID = 0x11U /*!< MMC MspDeInit Callback ID */ +}HAL_MMC_CallbackIDTypeDef; +/** + * @} + */ + +/** @defgroup MMC_Exported_Types_Group7 MMC Callback pointer definition + * @{ + */ +typedef void (*pMMC_CallbackTypeDef) (MMC_HandleTypeDef *hmmc); +/** + * @} + */ +#endif +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup MMC_Exported_Constants Exported Constants + * @{ + */ + +#define MMC_BLOCKSIZE 512U /*!< Block size is 512 bytes */ + +/** @defgroup MMC_Exported_Constansts_Group1 MMC Error status enumeration Structure definition + * @{ + */ +#define HAL_MMC_ERROR_NONE SDMMC_ERROR_NONE /*!< No error */ +#define HAL_MMC_ERROR_CMD_CRC_FAIL SDMMC_ERROR_CMD_CRC_FAIL /*!< Command response received (but CRC check failed) */ +#define HAL_MMC_ERROR_DATA_CRC_FAIL SDMMC_ERROR_DATA_CRC_FAIL /*!< Data block sent/received (CRC check failed) */ +#define HAL_MMC_ERROR_CMD_RSP_TIMEOUT SDMMC_ERROR_CMD_RSP_TIMEOUT /*!< Command response timeout */ +#define HAL_MMC_ERROR_DATA_TIMEOUT SDMMC_ERROR_DATA_TIMEOUT /*!< Data timeout */ +#define HAL_MMC_ERROR_TX_UNDERRUN SDMMC_ERROR_TX_UNDERRUN /*!< Transmit FIFO underrun */ +#define HAL_MMC_ERROR_RX_OVERRUN SDMMC_ERROR_RX_OVERRUN /*!< Receive FIFO overrun */ +#define HAL_MMC_ERROR_ADDR_MISALIGNED SDMMC_ERROR_ADDR_MISALIGNED /*!< Misaligned address */ +#define HAL_MMC_ERROR_BLOCK_LEN_ERR SDMMC_ERROR_BLOCK_LEN_ERR /*!< Transferred block length is not allowed for the card or the + number of transferred bytes does not match the block length */ +#define HAL_MMC_ERROR_ERASE_SEQ_ERR SDMMC_ERROR_ERASE_SEQ_ERR /*!< An error in the sequence of erase command occurs */ +#define HAL_MMC_ERROR_BAD_ERASE_PARAM SDMMC_ERROR_BAD_ERASE_PARAM /*!< An invalid selection for erase groups */ +#define HAL_MMC_ERROR_WRITE_PROT_VIOLATION SDMMC_ERROR_WRITE_PROT_VIOLATION /*!< Attempt to program a write protect block */ +#define HAL_MMC_ERROR_LOCK_UNLOCK_FAILED SDMMC_ERROR_LOCK_UNLOCK_FAILED /*!< Sequence or password error has been detected in unlock + command or if there was an attempt to access a locked card */ +#define HAL_MMC_ERROR_COM_CRC_FAILED SDMMC_ERROR_COM_CRC_FAILED /*!< CRC check of the previous command failed */ +#define HAL_MMC_ERROR_ILLEGAL_CMD SDMMC_ERROR_ILLEGAL_CMD /*!< Command is not legal for the card state */ +#define HAL_MMC_ERROR_CARD_ECC_FAILED SDMMC_ERROR_CARD_ECC_FAILED /*!< Card internal ECC was applied but failed to correct the data */ +#define HAL_MMC_ERROR_CC_ERR SDMMC_ERROR_CC_ERR /*!< Internal card controller error */ +#define HAL_MMC_ERROR_GENERAL_UNKNOWN_ERR SDMMC_ERROR_GENERAL_UNKNOWN_ERR /*!< General or unknown error */ +#define HAL_MMC_ERROR_STREAM_READ_UNDERRUN SDMMC_ERROR_STREAM_READ_UNDERRUN /*!< The card could not sustain data reading in stream rmode */ +#define HAL_MMC_ERROR_STREAM_WRITE_OVERRUN SDMMC_ERROR_STREAM_WRITE_OVERRUN /*!< The card could not sustain data programming in stream mode */ +#define HAL_MMC_ERROR_CID_CSD_OVERWRITE SDMMC_ERROR_CID_CSD_OVERWRITE /*!< CID/CSD overwrite error */ +#define HAL_MMC_ERROR_WP_ERASE_SKIP SDMMC_ERROR_WP_ERASE_SKIP /*!< Only partial address space was erased */ +#define HAL_MMC_ERROR_CARD_ECC_DISABLED SDMMC_ERROR_CARD_ECC_DISABLED /*!< Command has been executed without using internal ECC */ +#define HAL_MMC_ERROR_ERASE_RESET SDMMC_ERROR_ERASE_RESET /*!< Erase sequence was cleared before executing because an out + of erase sequence command was received */ +#define HAL_MMC_ERROR_AKE_SEQ_ERR SDMMC_ERROR_AKE_SEQ_ERR /*!< Error in sequence of authentication */ +#define HAL_MMC_ERROR_INVALID_VOLTRANGE SDMMC_ERROR_INVALID_VOLTRANGE /*!< Error in case of invalid voltage range */ +#define HAL_MMC_ERROR_ADDR_OUT_OF_RANGE SDMMC_ERROR_ADDR_OUT_OF_RANGE /*!< Error when addressed block is out of range */ +#define HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE SDMMC_ERROR_REQUEST_NOT_APPLICABLE /*!< Error when command request is not applicable */ +#define HAL_MMC_ERROR_PARAM SDMMC_ERROR_INVALID_PARAMETER /*!< the used parameter is not valid */ +#define HAL_MMC_ERROR_UNSUPPORTED_FEATURE SDMMC_ERROR_UNSUPPORTED_FEATURE /*!< Error when feature is not insupported */ +#define HAL_MMC_ERROR_BUSY SDMMC_ERROR_BUSY /*!< Error when transfer process is busy */ +#define HAL_MMC_ERROR_DMA SDMMC_ERROR_DMA /*!< Error while DMA transfer */ +#define HAL_MMC_ERROR_TIMEOUT SDMMC_ERROR_TIMEOUT /*!< Timeout error */ + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +#define HAL_MMC_ERROR_INVALID_CALLBACK SDMMC_ERROR_INVALID_PARAMETER /*!< Invalid callback error */ +#endif +/** + * @} + */ + +/** @defgroup MMC_Exported_Constansts_Group2 MMC context enumeration + * @{ + */ +#define MMC_CONTEXT_NONE 0x00000000U /*!< None */ +#define MMC_CONTEXT_READ_SINGLE_BLOCK 0x00000001U /*!< Read single block operation */ +#define MMC_CONTEXT_READ_MULTIPLE_BLOCK 0x00000002U /*!< Read multiple blocks operation */ +#define MMC_CONTEXT_WRITE_SINGLE_BLOCK 0x00000010U /*!< Write single block operation */ +#define MMC_CONTEXT_WRITE_MULTIPLE_BLOCK 0x00000020U /*!< Write multiple blocks operation */ +#define MMC_CONTEXT_IT 0x00000008U /*!< Process in Interrupt mode */ +#define MMC_CONTEXT_DMA 0x00000080U /*!< Process in DMA mode */ + +/** + * @} + */ + +/** @defgroup MMC_Exported_Constansts_Group3 MMC Voltage mode + * @{ + */ +/** + * @brief + */ +#define MMC_HIGH_VOLTAGE_RANGE 0x80FF8000U /*!< High voltage in byte mode */ +#define MMC_DUAL_VOLTAGE_RANGE 0x80FF8080U /*!< Dual voltage in byte mode */ +#define MMC_LOW_VOLTAGE_RANGE 0x80000080U /*!< Low voltage in byte mode */ +#define EMMC_HIGH_VOLTAGE_RANGE 0xC0FF8000U /*!< High voltage in sector mode */ +#define EMMC_DUAL_VOLTAGE_RANGE 0xC0FF8080U /*!< Dual voltage in sector mode */ +#define EMMC_LOW_VOLTAGE_RANGE 0xC0000080U /*!< Low voltage in sector mode */ +#define MMC_INVALID_VOLTAGE_RANGE 0x0001FF01U +/** + * @} + */ + +/** @defgroup MMC_Exported_Constansts_Group4 MMC Memory Cards + * @{ + */ +#define MMC_LOW_CAPACITY_CARD 0x00000000U /*!< MMC Card Capacity <=2Gbytes */ +#define MMC_HIGH_CAPACITY_CARD 0x00000001U /*!< MMC Card Capacity >2Gbytes and <2Tbytes */ + +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup MMC_Exported_macros MMC Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ +/** @brief Reset MMC handle state. + * @param __HANDLE__ : MMC handle. + * @retval None + */ +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +#define __HAL_MMC_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_MMC_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_MMC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_MMC_STATE_RESET) +#endif + +/** + * @brief Enable the MMC device. + * @retval None + */ +#define __HAL_MMC_ENABLE(__HANDLE__) __SDIO_ENABLE((__HANDLE__)->Instance) + +/** + * @brief Disable the MMC device. + * @retval None + */ +#define __HAL_MMC_DISABLE(__HANDLE__) __SDIO_DISABLE((__HANDLE__)->Instance) + +/** + * @brief Enable the SDMMC DMA transfer. + * @retval None + */ +#define __HAL_MMC_DMA_ENABLE(__HANDLE__) __SDIO_DMA_ENABLE((__HANDLE__)->Instance) + +/** + * @brief Disable the SDMMC DMA transfer. + * @retval None + */ +#define __HAL_MMC_DMA_DISABLE(__HANDLE__) __SDIO_DMA_DISABLE((__HANDLE__)->Instance) + +/** + * @brief Enable the MMC device interrupt. + * @param __HANDLE__: MMC Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt sources to be enabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @retval None + */ +#define __HAL_MMC_ENABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_ENABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Disable the MMC device interrupt. + * @param __HANDLE__: MMC Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt sources to be disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @retval None + */ +#define __HAL_MMC_DISABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_DISABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Check whether the specified MMC flag is set or not. + * @param __HANDLE__: MMC Handle + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDACT: Command transfer in progress + * @arg SDIO_FLAG_TXACT: Data transmit in progress + * @arg SDIO_FLAG_RXACT: Data receive in progress + * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty + * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full + * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full + * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full + * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty + * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty + * @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO + * @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received + * @retval The new state of MMC FLAG (SET or RESET). + */ +#define __HAL_MMC_GET_FLAG(__HANDLE__, __FLAG__) __SDIO_GET_FLAG((__HANDLE__)->Instance, (__FLAG__)) + +/** + * @brief Clear the MMC's pending flags. + * @param __HANDLE__: MMC Handle + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received + * @retval None + */ +#define __HAL_MMC_CLEAR_FLAG(__HANDLE__, __FLAG__) __SDIO_CLEAR_FLAG((__HANDLE__)->Instance, (__FLAG__)) + +/** + * @brief Check whether the specified MMC interrupt has occurred or not. + * @param __HANDLE__: MMC Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @retval The new state of MMC IT (SET or RESET). + */ +#define __HAL_MMC_GET_IT(__HANDLE__, __INTERRUPT__) __SDIO_GET_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Clear the MMC's interrupt pending bits. + * @param __HANDLE__: MMC Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt + * @retval None + */ +#define __HAL_MMC_CLEAR_IT(__HANDLE__, __INTERRUPT__) __SDIO_CLEAR_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup MMC_Exported_Functions MMC Exported Functions + * @{ + */ + +/** @defgroup MMC_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc); +HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc); +HAL_StatusTypeDef HAL_MMC_DeInit (MMC_HandleTypeDef *hmmc); +void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc); +void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc); + +/** + * @} + */ + +/** @defgroup MMC_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd); +/* Non-Blocking mode: IT */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); + +void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc); + +/* Callback in non blocking modes (DMA) */ +void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc); +void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc); +void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc); +void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc); + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +/* MMC callback registering/unregistering */ +HAL_StatusTypeDef HAL_MMC_RegisterCallback (MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId); +#endif +/** + * @} + */ + +/** @defgroup MMC_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode); +/** + * @} + */ + +/** @defgroup MMC_Exported_Functions_Group4 MMC card related functions + * @{ + */ +HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc); +HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID); +HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD); +HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo); +HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout); +/** + * @} + */ + +/** @defgroup MMC_Exported_Functions_Group5 Peripheral State and Errors functions + * @{ + */ +HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc); +uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc); +/** + * @} + */ + +/** @defgroup MMC_Exported_Functions_Group6 Peripheral Abort management + * @{ + */ +HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc); +HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc); +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup MMC_Private_Types MMC Private Types + * @{ + */ + +/** + * @} + */ + +/* Private defines -----------------------------------------------------------*/ +/** @defgroup MMC_Private_Defines MMC Private Defines + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup MMC_Private_Variables MMC Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup MMC_Private_Constants MMC Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup MMC_Private_Macros MMC Private Macros + * @{ + */ + +/** + * @} + */ + +/* Private functions prototypes ----------------------------------------------*/ +/** @defgroup MMC_Private_Functions_Prototypes MMC Private Functions Prototypes + * @{ + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup MMC_Private_Functions MMC Private Functions + * @{ + */ + +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* SDIO */ + +#endif /* STM32F4xx_HAL_MMC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h new file mode 100644 index 0000000..26f6502 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nand.h @@ -0,0 +1,388 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_nand.h + * @author MCD Application Team + * @brief Header file of NAND 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 STM32F4xx_HAL_NAND_H +#define STM32F4xx_HAL_NAND_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + +/* Includes ------------------------------------------------------------------*/ +#if defined(FSMC_Bank2_3) +#include "stm32f4xx_ll_fsmc.h" +#else +#include "stm32f4xx_ll_fmc.h" +#endif /* FSMC_Bank2_3 */ + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup NAND + * @{ + */ + +/* Exported typedef ----------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/** @defgroup NAND_Exported_Types NAND Exported Types + * @{ + */ + +/** + * @brief HAL NAND State structures definition + */ +typedef enum +{ + HAL_NAND_STATE_RESET = 0x00U, /*!< NAND not yet initialized or disabled */ + HAL_NAND_STATE_READY = 0x01U, /*!< NAND initialized and ready for use */ + HAL_NAND_STATE_BUSY = 0x02U, /*!< NAND internal process is ongoing */ + HAL_NAND_STATE_ERROR = 0x03U /*!< NAND error state */ +} HAL_NAND_StateTypeDef; + +/** + * @brief NAND Memory electronic signature Structure definition + */ +typedef struct +{ + /*State = HAL_NAND_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_NAND_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_NAND_STATE_RESET) +#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup NAND_Exported_Functions NAND Exported Functions + * @{ + */ + +/** @addtogroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, + FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing); +HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand); + +HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, NAND_DeviceConfigTypeDef *pDeviceConfig); + +HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID); + +void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand); +void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand); +void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand); +void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand); + +/** + * @} + */ + +/** @addtogroup NAND_Exported_Functions_Group2 Input and Output functions + * @{ + */ + +/* IO operation functions ****************************************************/ +HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand); + +HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, + uint32_t NumPageToRead); +HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, + uint32_t NumPageToWrite); +HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint8_t *pBuffer, uint32_t NumSpareAreaToRead); +HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint8_t *pBuffer, uint32_t NumSpareAreaTowrite); + +HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, + uint32_t NumPageToRead); +HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, + uint32_t NumPageToWrite); +HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint16_t *pBuffer, uint32_t NumSpareAreaToRead); +HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint16_t *pBuffer, uint32_t NumSpareAreaTowrite); + +HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress); + +uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress); + +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) +/* NAND callback registering/unregistering */ +HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId, + pNAND_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId); +#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup NAND_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ + +/* NAND Control functions ****************************************************/ +HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand); +HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand); +HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout); + +/** + * @} + */ + +/** @addtogroup NAND_Exported_Functions_Group4 Peripheral State functions + * @{ + */ +/* NAND State functions *******************************************************/ +HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand); +uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup NAND_Private_Constants NAND Private Constants + * @{ + */ +#if defined(FMC_Bank2_3) +#define NAND_DEVICE1 0x70000000UL +#define NAND_DEVICE2 0x80000000UL +#else +#define NAND_DEVICE 0x80000000UL +#endif +#define NAND_WRITE_TIMEOUT 0x01000000UL + +#define CMD_AREA (1UL<<16U) /* A16 = CLE high */ +#define ADDR_AREA (1UL<<17U) /* A17 = ALE high */ + +#define NAND_CMD_AREA_A ((uint8_t)0x00) +#define NAND_CMD_AREA_B ((uint8_t)0x01) +#define NAND_CMD_AREA_C ((uint8_t)0x50) +#define NAND_CMD_AREA_TRUE1 ((uint8_t)0x30) + +#define NAND_CMD_WRITE0 ((uint8_t)0x80) +#define NAND_CMD_WRITE_TRUE1 ((uint8_t)0x10) +#define NAND_CMD_ERASE0 ((uint8_t)0x60) +#define NAND_CMD_ERASE1 ((uint8_t)0xD0) +#define NAND_CMD_READID ((uint8_t)0x90) +#define NAND_CMD_STATUS ((uint8_t)0x70) +#define NAND_CMD_LOCK_STATUS ((uint8_t)0x7A) +#define NAND_CMD_RESET ((uint8_t)0xFF) + +/* NAND memory status */ +#define NAND_VALID_ADDRESS 0x00000100UL +#define NAND_INVALID_ADDRESS 0x00000200UL +#define NAND_TIMEOUT_ERROR 0x00000400UL +#define NAND_BUSY 0x00000000UL +#define NAND_ERROR 0x00000001UL +#define NAND_READY 0x00000040UL +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup NAND_Private_Macros NAND Private Macros + * @{ + */ + +/** + * @brief NAND memory address computation. + * @param __ADDRESS__ NAND memory address. + * @param __HANDLE__ NAND handle. + * @retval NAND Raw address value + */ +#define ARRAY_ADDRESS(__ADDRESS__ , __HANDLE__) ((__ADDRESS__)->Page + \ + (((__ADDRESS__)->Block + \ + (((__ADDRESS__)->Plane) * \ + ((__HANDLE__)->Config.PlaneSize))) * \ + ((__HANDLE__)->Config.BlockSize))) + +/** + * @brief NAND memory Column address computation. + * @param __HANDLE__ NAND handle. + * @retval NAND Raw address value + */ +#define COLUMN_ADDRESS( __HANDLE__) ((__HANDLE__)->Config.PageSize) + +/** + * @brief NAND memory address cycling. + * @param __ADDRESS__ NAND memory address. + * @retval NAND address cycling value. + */ +#define ADDR_1ST_CYCLE(__ADDRESS__) (uint8_t)(__ADDRESS__) /* 1st addressing cycle */ +#define ADDR_2ND_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 8) /* 2nd addressing cycle */ +#define ADDR_3RD_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 16) /* 3rd addressing cycle */ +#define ADDR_4TH_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 24) /* 4th addressing cycle */ + +/** + * @brief NAND memory Columns cycling. + * @param __ADDRESS__ NAND memory address. + * @retval NAND Column address cycling value. + */ +#define COLUMN_1ST_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) & 0xFFU) /* 1st Column addressing cycle */ +#define COLUMN_2ND_CYCLE(__ADDRESS__) (uint8_t)((__ADDRESS__) >> 8) /* 2nd Column addressing cycle */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank3) || defined(FMC_Bank2_3) || defined(FSMC_Bank2_3 */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_NAND_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h new file mode 100644 index 0000000..cc7f1b5 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_nor.h @@ -0,0 +1,330 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_nor.h + * @author MCD Application Team + * @brief Header file of NOR 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 STM32F4xx_HAL_NOR_H +#define STM32F4xx_HAL_NOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMC_Bank1) || defined(FSMC_Bank1) + +/* Includes ------------------------------------------------------------------*/ +#if defined(FSMC_Bank1) +#include "stm32f4xx_ll_fsmc.h" +#else +#include "stm32f4xx_ll_fmc.h" +#endif /* FMC_Bank1 */ + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup NOR + * @{ + */ + +/* Exported typedef ----------------------------------------------------------*/ +/** @defgroup NOR_Exported_Types NOR Exported Types + * @{ + */ + +/** + * @brief HAL SRAM State structures definition + */ +typedef enum +{ + HAL_NOR_STATE_RESET = 0x00U, /*!< NOR not yet initialized or disabled */ + HAL_NOR_STATE_READY = 0x01U, /*!< NOR initialized and ready for use */ + HAL_NOR_STATE_BUSY = 0x02U, /*!< NOR internal processing is ongoing */ + HAL_NOR_STATE_ERROR = 0x03U, /*!< NOR error state */ + HAL_NOR_STATE_PROTECTED = 0x04U /*!< NOR NORSRAM device write protected */ +} HAL_NOR_StateTypeDef; + +/** + * @brief FMC NOR Status typedef + */ +typedef enum +{ + HAL_NOR_STATUS_SUCCESS = 0U, + HAL_NOR_STATUS_ONGOING, + HAL_NOR_STATUS_ERROR, + HAL_NOR_STATUS_TIMEOUT +} HAL_NOR_StatusTypeDef; + +/** + * @brief FMC NOR ID typedef + */ +typedef struct +{ + uint16_t Manufacturer_Code; /*!< Defines the device's manufacturer code used to identify the memory */ + + uint16_t Device_Code1; + + uint16_t Device_Code2; + + uint16_t Device_Code3; /*!< Defines the device's codes used to identify the memory. + These codes can be accessed by performing read operations with specific + control signals and addresses set.They can also be accessed by issuing + an Auto Select command */ +} NOR_IDTypeDef; + +/** + * @brief FMC NOR CFI typedef + */ +typedef struct +{ + /*!< Defines the information stored in the memory's Common flash interface + which contains a description of various electrical and timing parameters, + density information and functions supported by the memory */ + + uint16_t CFI_1; + + uint16_t CFI_2; + + uint16_t CFI_3; + + uint16_t CFI_4; +} NOR_CFITypeDef; + +/** + * @brief NOR handle Structure definition + */ +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) +typedef struct __NOR_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_NOR_REGISTER_CALLBACKS */ + +{ + FMC_NORSRAM_TypeDef *Instance; /*!< Register base address */ + + FMC_NORSRAM_EXTENDED_TypeDef *Extended; /*!< Extended mode register base address */ + + FMC_NORSRAM_InitTypeDef Init; /*!< NOR device control configuration parameters */ + + HAL_LockTypeDef Lock; /*!< NOR locking object */ + + __IO HAL_NOR_StateTypeDef State; /*!< NOR device access state */ + + uint32_t CommandSet; /*!< NOR algorithm command set and control */ + +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __NOR_HandleTypeDef *hnor); /*!< NOR Msp Init callback */ + void (* MspDeInitCallback)(struct __NOR_HandleTypeDef *hnor); /*!< NOR Msp DeInit callback */ +#endif /* USE_HAL_NOR_REGISTER_CALLBACKS */ +} NOR_HandleTypeDef; + +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) +/** + * @brief HAL NOR Callback ID enumeration definition + */ +typedef enum +{ + HAL_NOR_MSP_INIT_CB_ID = 0x00U, /*!< NOR MspInit Callback ID */ + HAL_NOR_MSP_DEINIT_CB_ID = 0x01U /*!< NOR MspDeInit Callback ID */ +} HAL_NOR_CallbackIDTypeDef; + +/** + * @brief HAL NOR Callback pointer definition + */ +typedef void (*pNOR_CallbackTypeDef)(NOR_HandleTypeDef *hnor); +#endif /* USE_HAL_NOR_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup NOR_Exported_Macros NOR Exported Macros + * @{ + */ +/** @brief Reset NOR handle state + * @param __HANDLE__ specifies the NOR handle. + * @retval None + */ +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) +#define __HAL_NOR_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_NOR_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_NOR_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_NOR_STATE_RESET) +#endif /* USE_HAL_NOR_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup NOR_Exported_Functions NOR Exported Functions + * @{ + */ + +/** @addtogroup NOR_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_NOR_Init(NOR_HandleTypeDef *hnor, FMC_NORSRAM_TimingTypeDef *Timing, + FMC_NORSRAM_TimingTypeDef *ExtTiming); +HAL_StatusTypeDef HAL_NOR_DeInit(NOR_HandleTypeDef *hnor); +void HAL_NOR_MspInit(NOR_HandleTypeDef *hnor); +void HAL_NOR_MspDeInit(NOR_HandleTypeDef *hnor); +void HAL_NOR_MspWait(NOR_HandleTypeDef *hnor, uint32_t Timeout); +/** + * @} + */ + +/** @addtogroup NOR_Exported_Functions_Group2 Input and Output functions + * @{ + */ + +/* I/O operation functions ***************************************************/ +HAL_StatusTypeDef HAL_NOR_Read_ID(NOR_HandleTypeDef *hnor, NOR_IDTypeDef *pNOR_ID); +HAL_StatusTypeDef HAL_NOR_ReturnToReadMode(NOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData); +HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData); + +HAL_StatusTypeDef HAL_NOR_ReadBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData, + uint32_t uwBufferSize); +HAL_StatusTypeDef HAL_NOR_ProgramBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData, + uint32_t uwBufferSize); + +HAL_StatusTypeDef HAL_NOR_Erase_Block(NOR_HandleTypeDef *hnor, uint32_t BlockAddress, uint32_t Address); +HAL_StatusTypeDef HAL_NOR_Erase_Chip(NOR_HandleTypeDef *hnor, uint32_t Address); +HAL_StatusTypeDef HAL_NOR_Read_CFI(NOR_HandleTypeDef *hnor, NOR_CFITypeDef *pNOR_CFI); + +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) +/* NOR callback registering/unregistering */ +HAL_StatusTypeDef HAL_NOR_RegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId, + pNOR_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_NOR_UnRegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId); +#endif /* USE_HAL_NOR_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup NOR_Exported_Functions_Group3 NOR Control functions + * @{ + */ + +/* NOR Control functions *****************************************************/ +HAL_StatusTypeDef HAL_NOR_WriteOperation_Enable(NOR_HandleTypeDef *hnor); +HAL_StatusTypeDef HAL_NOR_WriteOperation_Disable(NOR_HandleTypeDef *hnor); +/** + * @} + */ + +/** @addtogroup NOR_Exported_Functions_Group4 NOR State functions + * @{ + */ + +/* NOR State functions ********************************************************/ +HAL_NOR_StateTypeDef HAL_NOR_GetState(NOR_HandleTypeDef *hnor); +HAL_NOR_StatusTypeDef HAL_NOR_GetStatus(NOR_HandleTypeDef *hnor, uint32_t Address, uint32_t Timeout); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup NOR_Private_Constants NOR Private Constants + * @{ + */ +/* NOR device IDs addresses */ +#define MC_ADDRESS ((uint16_t)0x0000) +#define DEVICE_CODE1_ADDR ((uint16_t)0x0001) +#define DEVICE_CODE2_ADDR ((uint16_t)0x000E) +#define DEVICE_CODE3_ADDR ((uint16_t)0x000F) + +/* NOR CFI IDs addresses */ +#define CFI1_ADDRESS ((uint16_t)0x0061) +#define CFI2_ADDRESS ((uint16_t)0x0062) +#define CFI3_ADDRESS ((uint16_t)0x0063) +#define CFI4_ADDRESS ((uint16_t)0x0064) + +/* NOR operation wait timeout */ +#define NOR_TMEOUT ((uint16_t)0xFFFF) + +/* NOR memory data width */ +#define NOR_MEMORY_8B ((uint8_t)0x00) +#define NOR_MEMORY_16B ((uint8_t)0x01) + +/* NOR memory device read/write start address */ +#define NOR_MEMORY_ADRESS1 (0x60000000U) +#define NOR_MEMORY_ADRESS2 (0x64000000U) +#define NOR_MEMORY_ADRESS3 (0x68000000U) +#define NOR_MEMORY_ADRESS4 (0x6C000000U) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup NOR_Private_Macros NOR Private Macros + * @{ + */ +/** + * @brief NOR memory address shifting. + * @param __NOR_ADDRESS NOR base address + * @param __NOR_MEMORY_WIDTH_ NOR memory width + * @param __ADDRESS__ NOR memory address + * @retval NOR shifted address value + */ +#define NOR_ADDR_SHIFT(__NOR_ADDRESS, __NOR_MEMORY_WIDTH_, __ADDRESS__) \ + ((uint32_t)(((__NOR_MEMORY_WIDTH_) == NOR_MEMORY_16B)? \ + ((uint32_t)((__NOR_ADDRESS) + (2U * (__ADDRESS__)))): \ + ((uint32_t)((__NOR_ADDRESS) + (__ADDRESS__))))) + +/** + * @brief NOR memory write data to specified address. + * @param __ADDRESS__ NOR memory address + * @param __DATA__ Data to write + * @retval None + */ +#define NOR_WRITE(__ADDRESS__, __DATA__) do{ \ + (*(__IO uint16_t *)((uint32_t)(__ADDRESS__)) = (__DATA__)); \ + __DSB(); \ + } while(0) + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank1 || FSMC_Bank1 */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_NOR_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h new file mode 100644 index 0000000..47fbb26 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pccard.h @@ -0,0 +1,285 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_pccard.h + * @author MCD Application Team + * @brief Header file of PCCARD 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 STM32F4xx_HAL_PCCARD_H +#define STM32F4xx_HAL_PCCARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMC_Bank4) || defined(FSMC_Bank4) + +/* Includes ------------------------------------------------------------------*/ +#if defined(FSMC_Bank4) +#include "stm32f4xx_ll_fsmc.h" +#else +#include "stm32f4xx_ll_fmc.h" +#endif /* FSMC_Bank4 */ + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup PCCARD + * @{ + */ + +/* Exported typedef ----------------------------------------------------------*/ +/** @defgroup PCCARD_Exported_Types PCCARD Exported Types + * @{ + */ + +/** + * @brief HAL PCCARD State structures definition + */ +typedef enum +{ + HAL_PCCARD_STATE_RESET = 0x00U, /*!< PCCARD peripheral not yet initialized or disabled */ + HAL_PCCARD_STATE_READY = 0x01U, /*!< PCCARD peripheral ready */ + HAL_PCCARD_STATE_BUSY = 0x02U, /*!< PCCARD peripheral busy */ + HAL_PCCARD_STATE_ERROR = 0x04U /*!< PCCARD peripheral error */ +} HAL_PCCARD_StateTypeDef; + +typedef enum +{ + HAL_PCCARD_STATUS_SUCCESS = 0U, + HAL_PCCARD_STATUS_ONGOING, + HAL_PCCARD_STATUS_ERROR, + HAL_PCCARD_STATUS_TIMEOUT +} HAL_PCCARD_StatusTypeDef; + +/** + * @brief FMC_PCCARD handle Structure definition + */ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) +typedef struct __PCCARD_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */ +{ + FMC_PCCARD_TypeDef *Instance; /*!< Register base address for PCCARD device */ + + FMC_PCCARD_InitTypeDef Init; /*!< PCCARD device control configuration parameters */ + + __IO HAL_PCCARD_StateTypeDef State; /*!< PCCARD device access state */ + + HAL_LockTypeDef Lock; /*!< PCCARD Lock */ + +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __PCCARD_HandleTypeDef *hpccard); /*!< PCCARD Msp Init callback */ + void (* MspDeInitCallback)(struct __PCCARD_HandleTypeDef *hpccard); /*!< PCCARD Msp DeInit callback */ + void (* ItCallback)(struct __PCCARD_HandleTypeDef *hpccard); /*!< PCCARD IT callback */ +#endif +} PCCARD_HandleTypeDef; + +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) +/** + * @brief HAL PCCARD Callback ID enumeration definition + */ +typedef enum +{ + HAL_PCCARD_MSP_INIT_CB_ID = 0x00U, /*!< PCCARD MspInit Callback ID */ + HAL_PCCARD_MSP_DEINIT_CB_ID = 0x01U, /*!< PCCARD MspDeInit Callback ID */ + HAL_PCCARD_IT_CB_ID = 0x02U /*!< PCCARD IT Callback ID */ +} HAL_PCCARD_CallbackIDTypeDef; + +/** + * @brief HAL PCCARD Callback pointer definition + */ +typedef void (*pPCCARD_CallbackTypeDef)(PCCARD_HandleTypeDef *hpccard); +#endif +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup PCCARD_Exported_Macros PCCARD Exported Macros + * @{ + */ +/** @brief Reset PCCARD handle state + * @param __HANDLE__ specifies the PCCARD handle. + * @retval None + */ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) +#define __HAL_PCCARD_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_PCCARD_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_PCCARD_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_PCCARD_STATE_RESET) +#endif +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup PCCARD_Exported_Functions + * @{ + */ + +/** @addtogroup PCCARD_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FMC_NAND_PCC_TimingTypeDef *ComSpaceTiming, + FMC_NAND_PCC_TimingTypeDef *AttSpaceTiming, FMC_NAND_PCC_TimingTypeDef *IOSpaceTiming); +HAL_StatusTypeDef HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard); +void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard); +void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard); +/** + * @} + */ + +/** @addtogroup PCCARD_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *****************************************************/ +HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus); +HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress, + uint8_t *pStatus); +HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress, + uint8_t *pStatus); +HAL_StatusTypeDef HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus); +HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard); +void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard); +void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard); + +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) +/* PCCARD callback registering/unregistering */ +HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId, + pPCCARD_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, + HAL_PCCARD_CallbackIDTypeDef CallbackId); +#endif +/** + * @} + */ + +/** @addtogroup PCCARD_Exported_Functions_Group3 + * @{ + */ +/* PCCARD State functions *******************************************************/ +HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard); +HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard); +HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup PCCARD_Private_Constants PCCARD Private Constants + * @{ + */ +#define PCCARD_DEVICE_ADDRESS 0x90000000U +#define PCCARD_ATTRIBUTE_SPACE_ADDRESS 0x98000000U /* Attribute space size to @0x9BFF FFFF */ +#define PCCARD_COMMON_SPACE_ADDRESS PCCARD_DEVICE_ADDRESS /* Common space size to @0x93FF FFFF */ +#define PCCARD_IO_SPACE_ADDRESS 0x9C000000U /* IO space size to @0x9FFF FFFF */ +#define PCCARD_IO_SPACE_PRIMARY_ADDR 0x9C0001F0U /* IO space size to @0x9FFF FFFF */ + +/* Flash-ATA registers description */ +#define ATA_DATA ((uint8_t)0x00) /* Data register */ +#define ATA_SECTOR_COUNT ((uint8_t)0x02) /* Sector Count register */ +#define ATA_SECTOR_NUMBER ((uint8_t)0x03) /* Sector Number register */ +#define ATA_CYLINDER_LOW ((uint8_t)0x04) /* Cylinder low register */ +#define ATA_CYLINDER_HIGH ((uint8_t)0x05) /* Cylinder high register */ +#define ATA_CARD_HEAD ((uint8_t)0x06) /* Card/Head register */ +#define ATA_STATUS_CMD ((uint8_t)0x07) /* Status(read)/Command(write) register */ +#define ATA_STATUS_CMD_ALTERNATE ((uint8_t)0x0E) /* Alternate Status(read)/Command(write) register */ +#define ATA_COMMON_DATA_AREA ((uint16_t)0x0400) /* Start of data area (for Common access only!) */ +#define ATA_CARD_CONFIGURATION ((uint16_t)0x0202) /* Card Configuration and Status Register */ + +/* Flash-ATA commands */ +#define ATA_READ_SECTOR_CMD ((uint8_t)0x20) +#define ATA_WRITE_SECTOR_CMD ((uint8_t)0x30) +#define ATA_ERASE_SECTOR_CMD ((uint8_t)0xC0) +#define ATA_IDENTIFY_CMD ((uint8_t)0xEC) + +/* PC Card/Compact Flash status */ +#define PCCARD_TIMEOUT_ERROR ((uint8_t)0x60) +#define PCCARD_BUSY ((uint8_t)0x80) +#define PCCARD_PROGR ((uint8_t)0x01) +#define PCCARD_READY ((uint8_t)0x40) + +#define PCCARD_SECTOR_SIZE 255U /* In half words */ + +/** + * @} + */ +/* Compact Flash redefinition */ +#define HAL_CF_Init HAL_PCCARD_Init +#define HAL_CF_DeInit HAL_PCCARD_DeInit +#define HAL_CF_MspInit HAL_PCCARD_MspInit +#define HAL_CF_MspDeInit HAL_PCCARD_MspDeInit + +#define HAL_CF_Read_ID HAL_PCCARD_Read_ID +#define HAL_CF_Write_Sector HAL_PCCARD_Write_Sector +#define HAL_CF_Read_Sector HAL_PCCARD_Read_Sector +#define HAL_CF_Erase_Sector HAL_PCCARD_Erase_Sector +#define HAL_CF_Reset HAL_PCCARD_Reset +#define HAL_CF_IRQHandler HAL_PCCARD_IRQHandler +#define HAL_CF_ITCallback HAL_PCCARD_ITCallback + +#define HAL_CF_GetState HAL_PCCARD_GetState +#define HAL_CF_GetStatus HAL_PCCARD_GetStatus +#define HAL_CF_ReadStatus HAL_PCCARD_ReadStatus + +#define HAL_CF_STATUS_SUCCESS HAL_PCCARD_STATUS_SUCCESS +#define HAL_CF_STATUS_ONGOING HAL_PCCARD_STATUS_ONGOING +#define HAL_CF_STATUS_ERROR HAL_PCCARD_STATUS_ERROR +#define HAL_CF_STATUS_TIMEOUT HAL_PCCARD_STATUS_TIMEOUT +#define HAL_CF_StatusTypeDef HAL_PCCARD_StatusTypeDef + +#define CF_DEVICE_ADDRESS PCCARD_DEVICE_ADDRESS +#define CF_ATTRIBUTE_SPACE_ADDRESS PCCARD_ATTRIBUTE_SPACE_ADDRESS +#define CF_COMMON_SPACE_ADDRESS PCCARD_COMMON_SPACE_ADDRESS +#define CF_IO_SPACE_ADDRESS PCCARD_IO_SPACE_ADDRESS +#define CF_IO_SPACE_PRIMARY_ADDR PCCARD_IO_SPACE_PRIMARY_ADDR + +#define CF_TIMEOUT_ERROR PCCARD_TIMEOUT_ERROR +#define CF_BUSY PCCARD_BUSY +#define CF_PROGR PCCARD_PROGR +#define CF_READY PCCARD_READY + +#define CF_SECTOR_SIZE PCCARD_SECTOR_SIZE + +/* Private macros ------------------------------------------------------------*/ +/** + * @} + */ + + +/** + * @} + */ + +#endif /* FMC_Bank4 || FSMC_Bank4 */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_PCCARD_H */ diff --git a/libs/hal/stm32f4xx_hal_pcd.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h similarity index 100% rename from libs/hal/stm32f4xx_hal_pcd.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd.h diff --git a/libs/hal/stm32f4xx_hal_pcd_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_pcd_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pcd_ex.h diff --git a/libs/hal/stm32f4xx_hal_pwr.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h similarity index 100% rename from libs/hal/stm32f4xx_hal_pwr.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr.h diff --git a/libs/hal/stm32f4xx_hal_pwr_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h similarity index 100% rename from libs/hal/stm32f4xx_hal_pwr_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_pwr_ex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h new file mode 100644 index 0000000..56287af --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_qspi.h @@ -0,0 +1,750 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_qspi.h + * @author MCD Application Team + * @brief Header file of QSPI 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 STM32F4xx_HAL_QSPI_H +#define STM32F4xx_HAL_QSPI_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined(QUADSPI) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup QSPI + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup QSPI_Exported_Types QSPI Exported Types + * @{ + */ + +/** + * @brief QSPI Init structure definition + */ +typedef struct +{ + uint32_t ClockPrescaler; /* Specifies the prescaler factor for generating clock based on the AHB clock. + This parameter can be a number between 0 and 255 */ + uint32_t FifoThreshold; /* Specifies the threshold number of bytes in the FIFO (used only in indirect mode) + This parameter can be a value between 1 and 32 */ + uint32_t SampleShifting; /* Specifies the Sample Shift. The data is sampled 1/2 clock cycle delay later to + take in account external signal delays. (It should be QSPI_SAMPLE_SHIFTING_NONE in DDR mode) + This parameter can be a value of @ref QSPI_SampleShifting */ + uint32_t FlashSize; /* Specifies the Flash Size. FlashSize+1 is effectively the number of address bits + required to address the flash memory. The flash capacity can be up to 4GB + (addressed using 32 bits) in indirect mode, but the addressable space in + memory-mapped mode is limited to 256MB + This parameter can be a number between 0 and 31 */ + uint32_t ChipSelectHighTime; /* Specifies the Chip Select High Time. ChipSelectHighTime+1 defines the minimum number + of clock cycles which the chip select must remain high between commands. + This parameter can be a value of @ref QSPI_ChipSelectHighTime */ + uint32_t ClockMode; /* Specifies the Clock Mode. It indicates the level that clock takes between commands. + This parameter can be a value of @ref QSPI_ClockMode */ + uint32_t FlashID; /* Specifies the Flash which will be used, + This parameter can be a value of @ref QSPI_Flash_Select */ + uint32_t DualFlash; /* Specifies the Dual Flash Mode State + This parameter can be a value of @ref QSPI_DualFlash_Mode */ +}QSPI_InitTypeDef; + +/** + * @brief HAL QSPI State structures definition + */ +typedef enum +{ + HAL_QSPI_STATE_RESET = 0x00U, /*!< Peripheral not initialized */ + HAL_QSPI_STATE_READY = 0x01U, /*!< Peripheral initialized and ready for use */ + HAL_QSPI_STATE_BUSY = 0x02U, /*!< Peripheral in indirect mode and busy */ + HAL_QSPI_STATE_BUSY_INDIRECT_TX = 0x12U, /*!< Peripheral in indirect mode with transmission ongoing */ + HAL_QSPI_STATE_BUSY_INDIRECT_RX = 0x22U, /*!< Peripheral in indirect mode with reception ongoing */ + HAL_QSPI_STATE_BUSY_AUTO_POLLING = 0x42U, /*!< Peripheral in auto polling mode ongoing */ + HAL_QSPI_STATE_BUSY_MEM_MAPPED = 0x82U, /*!< Peripheral in memory mapped mode ongoing */ + HAL_QSPI_STATE_ABORT = 0x08U, /*!< Peripheral with abort request ongoing */ + HAL_QSPI_STATE_ERROR = 0x04U /*!< Peripheral in error */ +}HAL_QSPI_StateTypeDef; + +/** + * @brief QSPI Handle Structure definition + */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +typedef struct __QSPI_HandleTypeDef +#else +typedef struct +#endif +{ + QUADSPI_TypeDef *Instance; /* QSPI registers base address */ + QSPI_InitTypeDef Init; /* QSPI communication parameters */ + uint8_t *pTxBuffPtr; /* Pointer to QSPI Tx transfer Buffer */ + __IO uint32_t TxXferSize; /* QSPI Tx Transfer size */ + __IO uint32_t TxXferCount; /* QSPI Tx Transfer Counter */ + uint8_t *pRxBuffPtr; /* Pointer to QSPI Rx transfer Buffer */ + __IO uint32_t RxXferSize; /* QSPI Rx Transfer size */ + __IO uint32_t RxXferCount; /* QSPI Rx Transfer Counter */ + DMA_HandleTypeDef *hdma; /* QSPI Rx/Tx DMA Handle parameters */ + __IO HAL_LockTypeDef Lock; /* Locking object */ + __IO HAL_QSPI_StateTypeDef State; /* QSPI communication state */ + __IO uint32_t ErrorCode; /* QSPI Error code */ + uint32_t Timeout; /* Timeout for the QSPI memory access */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + void (* ErrorCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* AbortCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* FifoThresholdCallback)(struct __QSPI_HandleTypeDef *hqspi); + void (* CmdCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* RxCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* TxCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* RxHalfCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* TxHalfCpltCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* StatusMatchCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* TimeOutCallback) (struct __QSPI_HandleTypeDef *hqspi); + + void (* MspInitCallback) (struct __QSPI_HandleTypeDef *hqspi); + void (* MspDeInitCallback) (struct __QSPI_HandleTypeDef *hqspi); +#endif +}QSPI_HandleTypeDef; + +/** + * @brief QSPI Command structure definition + */ +typedef struct +{ + uint32_t Instruction; /* Specifies the Instruction to be sent + This parameter can be a value (8-bit) between 0x00 and 0xFF */ + uint32_t Address; /* Specifies the Address to be sent (Size from 1 to 4 bytes according AddressSize) + This parameter can be a value (32-bits) between 0x0 and 0xFFFFFFFF */ + uint32_t AlternateBytes; /* Specifies the Alternate Bytes to be sent (Size from 1 to 4 bytes according AlternateBytesSize) + This parameter can be a value (32-bits) between 0x0 and 0xFFFFFFFF */ + uint32_t AddressSize; /* Specifies the Address Size + This parameter can be a value of @ref QSPI_AddressSize */ + uint32_t AlternateBytesSize; /* Specifies the Alternate Bytes Size + This parameter can be a value of @ref QSPI_AlternateBytesSize */ + uint32_t DummyCycles; /* Specifies the Number of Dummy Cycles. + This parameter can be a number between 0 and 31 */ + uint32_t InstructionMode; /* Specifies the Instruction Mode + This parameter can be a value of @ref QSPI_InstructionMode */ + uint32_t AddressMode; /* Specifies the Address Mode + This parameter can be a value of @ref QSPI_AddressMode */ + uint32_t AlternateByteMode; /* Specifies the Alternate Bytes Mode + This parameter can be a value of @ref QSPI_AlternateBytesMode */ + uint32_t DataMode; /* Specifies the Data Mode (used for dummy cycles and data phases) + This parameter can be a value of @ref QSPI_DataMode */ + uint32_t NbData; /* Specifies the number of data to transfer. (This is the number of bytes) + This parameter can be any value between 0 and 0xFFFFFFFF (0 means undefined length + until end of memory)*/ + uint32_t DdrMode; /* Specifies the double data rate mode for address, alternate byte and data phase + This parameter can be a value of @ref QSPI_DdrMode */ + uint32_t DdrHoldHalfCycle; /* Specifies if the DDR hold is enabled. When enabled it delays the data + output by one half of system clock in DDR mode. + This parameter can be a value of @ref QSPI_DdrHoldHalfCycle */ + uint32_t SIOOMode; /* Specifies the send instruction only once mode + This parameter can be a value of @ref QSPI_SIOOMode */ +}QSPI_CommandTypeDef; + +/** + * @brief QSPI Auto Polling mode configuration structure definition + */ +typedef struct +{ + uint32_t Match; /* Specifies the value to be compared with the masked status register to get a match. + This parameter can be any value between 0 and 0xFFFFFFFF */ + uint32_t Mask; /* Specifies the mask to be applied to the status bytes received. + This parameter can be any value between 0 and 0xFFFFFFFF */ + uint32_t Interval; /* Specifies the number of clock cycles between two read during automatic polling phases. + This parameter can be any value between 0 and 0xFFFF */ + uint32_t StatusBytesSize; /* Specifies the size of the status bytes received. + This parameter can be any value between 1 and 4 */ + uint32_t MatchMode; /* Specifies the method used for determining a match. + This parameter can be a value of @ref QSPI_MatchMode */ + uint32_t AutomaticStop; /* Specifies if automatic polling is stopped after a match. + This parameter can be a value of @ref QSPI_AutomaticStop */ +}QSPI_AutoPollingTypeDef; + +/** + * @brief QSPI Memory Mapped mode configuration structure definition + */ +typedef struct +{ + uint32_t TimeOutPeriod; /* Specifies the number of clock to wait when the FIFO is full before to release the chip select. + This parameter can be any value between 0 and 0xFFFF */ + uint32_t TimeOutActivation; /* Specifies if the timeout counter is enabled to release the chip select. + This parameter can be a value of @ref QSPI_TimeOutActivation */ +}QSPI_MemoryMappedTypeDef; + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +/** + * @brief HAL QSPI Callback ID enumeration definition + */ +typedef enum +{ + HAL_QSPI_ERROR_CB_ID = 0x00U, /*!< QSPI Error Callback ID */ + HAL_QSPI_ABORT_CB_ID = 0x01U, /*!< QSPI Abort Callback ID */ + HAL_QSPI_FIFO_THRESHOLD_CB_ID = 0x02U, /*!< QSPI FIFO Threshold Callback ID */ + HAL_QSPI_CMD_CPLT_CB_ID = 0x03U, /*!< QSPI Command Complete Callback ID */ + HAL_QSPI_RX_CPLT_CB_ID = 0x04U, /*!< QSPI Rx Complete Callback ID */ + HAL_QSPI_TX_CPLT_CB_ID = 0x05U, /*!< QSPI Tx Complete Callback ID */ + HAL_QSPI_RX_HALF_CPLT_CB_ID = 0x06U, /*!< QSPI Rx Half Complete Callback ID */ + HAL_QSPI_TX_HALF_CPLT_CB_ID = 0x07U, /*!< QSPI Tx Half Complete Callback ID */ + HAL_QSPI_STATUS_MATCH_CB_ID = 0x08U, /*!< QSPI Status Match Callback ID */ + HAL_QSPI_TIMEOUT_CB_ID = 0x09U, /*!< QSPI Timeout Callback ID */ + + HAL_QSPI_MSP_INIT_CB_ID = 0x0AU, /*!< QSPI MspInit Callback ID */ + HAL_QSPI_MSP_DEINIT_CB_ID = 0x0B0 /*!< QSPI MspDeInit Callback ID */ +}HAL_QSPI_CallbackIDTypeDef; + +/** + * @brief HAL QSPI Callback pointer definition + */ +typedef void (*pQSPI_CallbackTypeDef)(QSPI_HandleTypeDef *hqspi); +#endif +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup QSPI_Exported_Constants QSPI Exported Constants + * @{ + */ + +/** @defgroup QSPI_ErrorCode QSPI Error Code + * @{ + */ +#define HAL_QSPI_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_QSPI_ERROR_TIMEOUT 0x00000001U /*!< Timeout error */ +#define HAL_QSPI_ERROR_TRANSFER 0x00000002U /*!< Transfer error */ +#define HAL_QSPI_ERROR_DMA 0x00000004U /*!< DMA transfer error */ +#define HAL_QSPI_ERROR_INVALID_PARAM 0x00000008U /*!< Invalid parameters error */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +#define HAL_QSPI_ERROR_INVALID_CALLBACK 0x00000010U /*!< Invalid callback error */ +#endif +/** + * @} + */ + +/** @defgroup QSPI_SampleShifting QSPI Sample Shifting + * @{ + */ +#define QSPI_SAMPLE_SHIFTING_NONE 0x00000000U /*!State = HAL_QSPI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_QSPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_QSPI_STATE_RESET) +#endif + +/** @brief Enable the QSPI peripheral. + * @param __HANDLE__ specifies the QSPI Handle. + * @retval None + */ +#define __HAL_QSPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR, QUADSPI_CR_EN) + +/** @brief Disable the QSPI peripheral. + * @param __HANDLE__ specifies the QSPI Handle. + * @retval None + */ +#define __HAL_QSPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR, QUADSPI_CR_EN) + +/** @brief Enable the specified QSPI interrupt. + * @param __HANDLE__ specifies the QSPI Handle. + * @param __INTERRUPT__ specifies the QSPI interrupt source to enable. + * This parameter can be one of the following values: + * @arg QSPI_IT_TO: QSPI Timeout interrupt + * @arg QSPI_IT_SM: QSPI Status match interrupt + * @arg QSPI_IT_FT: QSPI FIFO threshold interrupt + * @arg QSPI_IT_TC: QSPI Transfer complete interrupt + * @arg QSPI_IT_TE: QSPI Transfer error interrupt + * @retval None + */ +#define __HAL_QSPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__)) + + +/** @brief Disable the specified QSPI interrupt. + * @param __HANDLE__ specifies the QSPI Handle. + * @param __INTERRUPT__ specifies the QSPI interrupt source to disable. + * This parameter can be one of the following values: + * @arg QSPI_IT_TO: QSPI Timeout interrupt + * @arg QSPI_IT_SM: QSPI Status match interrupt + * @arg QSPI_IT_FT: QSPI FIFO threshold interrupt + * @arg QSPI_IT_TC: QSPI Transfer complete interrupt + * @arg QSPI_IT_TE: QSPI Transfer error interrupt + * @retval None + */ +#define __HAL_QSPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__)) + +/** @brief Check whether the specified QSPI interrupt source is enabled or not. + * @param __HANDLE__ specifies the QSPI Handle. + * @param __INTERRUPT__ specifies the QSPI interrupt source to check. + * This parameter can be one of the following values: + * @arg QSPI_IT_TO: QSPI Timeout interrupt + * @arg QSPI_IT_SM: QSPI Status match interrupt + * @arg QSPI_IT_FT: QSPI FIFO threshold interrupt + * @arg QSPI_IT_TC: QSPI Transfer complete interrupt + * @arg QSPI_IT_TE: QSPI Transfer error interrupt + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_QSPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (READ_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Check whether the selected QSPI flag is set or not. + * @param __HANDLE__ specifies the QSPI Handle. + * @param __FLAG__ specifies the QSPI flag to check. + * This parameter can be one of the following values: + * @arg QSPI_FLAG_BUSY: QSPI Busy flag + * @arg QSPI_FLAG_TO: QSPI Timeout flag + * @arg QSPI_FLAG_SM: QSPI Status match flag + * @arg QSPI_FLAG_FT: QSPI FIFO threshold flag + * @arg QSPI_FLAG_TC: QSPI Transfer complete flag + * @arg QSPI_FLAG_TE: QSPI Transfer error flag + * @retval None + */ +#define __HAL_QSPI_GET_FLAG(__HANDLE__, __FLAG__) ((READ_BIT((__HANDLE__)->Instance->SR, (__FLAG__)) != 0U) ? SET : RESET) + +/** @brief Clears the specified QSPI's flag status. + * @param __HANDLE__ specifies the QSPI Handle. + * @param __FLAG__ specifies the QSPI clear register flag that needs to be set + * This parameter can be one of the following values: + * @arg QSPI_FLAG_TO: QSPI Timeout flag + * @arg QSPI_FLAG_SM: QSPI Status match flag + * @arg QSPI_FLAG_TC: QSPI Transfer complete flag + * @arg QSPI_FLAG_TE: QSPI Transfer error flag + * @retval None + */ +#define __HAL_QSPI_CLEAR_FLAG(__HANDLE__, __FLAG__) WRITE_REG((__HANDLE__)->Instance->FCR, (__FLAG__)) +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup QSPI_Exported_Functions + * @{ + */ + +/** @addtogroup QSPI_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_QSPI_Init (QSPI_HandleTypeDef *hqspi); +HAL_StatusTypeDef HAL_QSPI_DeInit (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_MspInit (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi); +/** + * @} + */ + +/** @addtogroup QSPI_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *****************************************************/ +/* QSPI IRQ handler method */ +void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi); + +/* QSPI indirect mode */ +HAL_StatusTypeDef HAL_QSPI_Command (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout); +HAL_StatusTypeDef HAL_QSPI_Transmit (QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout); +HAL_StatusTypeDef HAL_QSPI_Receive (QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout); +HAL_StatusTypeDef HAL_QSPI_Command_IT (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd); +HAL_StatusTypeDef HAL_QSPI_Transmit_IT (QSPI_HandleTypeDef *hqspi, uint8_t *pData); +HAL_StatusTypeDef HAL_QSPI_Receive_IT (QSPI_HandleTypeDef *hqspi, uint8_t *pData); +HAL_StatusTypeDef HAL_QSPI_Transmit_DMA (QSPI_HandleTypeDef *hqspi, uint8_t *pData); +HAL_StatusTypeDef HAL_QSPI_Receive_DMA (QSPI_HandleTypeDef *hqspi, uint8_t *pData); + +/* QSPI status flag polling mode */ +HAL_StatusTypeDef HAL_QSPI_AutoPolling (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout); +HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg); + +/* QSPI memory-mapped mode */ +HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg); + +/* Callback functions in non-blocking modes ***********************************/ +void HAL_QSPI_ErrorCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_AbortCpltCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi); + +/* QSPI indirect mode */ +void HAL_QSPI_CmdCpltCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_RxCpltCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_TxCpltCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_RxHalfCpltCallback (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_TxHalfCpltCallback (QSPI_HandleTypeDef *hqspi); + +/* QSPI status flag polling mode */ +void HAL_QSPI_StatusMatchCallback (QSPI_HandleTypeDef *hqspi); + +/* QSPI memory-mapped mode */ +void HAL_QSPI_TimeOutCallback (QSPI_HandleTypeDef *hqspi); + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +/* QSPI callback registering/unregistering */ +HAL_StatusTypeDef HAL_QSPI_RegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId, pQSPI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_QSPI_UnRegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId); +#endif +/** + * @} + */ + +/** @addtogroup QSPI_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control and State functions ************************************/ +HAL_QSPI_StateTypeDef HAL_QSPI_GetState (QSPI_HandleTypeDef *hqspi); +uint32_t HAL_QSPI_GetError (QSPI_HandleTypeDef *hqspi); +HAL_StatusTypeDef HAL_QSPI_Abort (QSPI_HandleTypeDef *hqspi); +HAL_StatusTypeDef HAL_QSPI_Abort_IT (QSPI_HandleTypeDef *hqspi); +void HAL_QSPI_SetTimeout (QSPI_HandleTypeDef *hqspi, uint32_t Timeout); +HAL_StatusTypeDef HAL_QSPI_SetFifoThreshold(QSPI_HandleTypeDef *hqspi, uint32_t Threshold); +uint32_t HAL_QSPI_GetFifoThreshold(QSPI_HandleTypeDef *hqspi); +HAL_StatusTypeDef HAL_QSPI_SetFlashID (QSPI_HandleTypeDef *hqspi, uint32_t FlashID); +/** + * @} + */ + +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup QSPI_Private_Macros QSPI Private Macros + * @{ + */ +#define IS_QSPI_CLOCK_PRESCALER(PRESCALER) ((PRESCALER) <= 0xFFU) + +#define IS_QSPI_FIFO_THRESHOLD(THR) (((THR) > 0U) && ((THR) <= 32U)) + +#define IS_QSPI_SSHIFT(SSHIFT) (((SSHIFT) == QSPI_SAMPLE_SHIFTING_NONE) || \ + ((SSHIFT) == QSPI_SAMPLE_SHIFTING_HALFCYCLE)) + +#define IS_QSPI_FLASH_SIZE(FSIZE) (((FSIZE) <= 31U)) + +#define IS_QSPI_CS_HIGH_TIME(CSHTIME) (((CSHTIME) == QSPI_CS_HIGH_TIME_1_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_2_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_3_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_4_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_5_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_6_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_7_CYCLE) || \ + ((CSHTIME) == QSPI_CS_HIGH_TIME_8_CYCLE)) + +#define IS_QSPI_CLOCK_MODE(CLKMODE) (((CLKMODE) == QSPI_CLOCK_MODE_0) || \ + ((CLKMODE) == QSPI_CLOCK_MODE_3)) + +#define IS_QSPI_FLASH_ID(FLASH_ID) (((FLASH_ID) == QSPI_FLASH_ID_1) || \ + ((FLASH_ID) == QSPI_FLASH_ID_2)) + +#define IS_QSPI_DUAL_FLASH_MODE(MODE) (((MODE) == QSPI_DUALFLASH_ENABLE) || \ + ((MODE) == QSPI_DUALFLASH_DISABLE)) + +#define IS_QSPI_INSTRUCTION(INSTRUCTION) ((INSTRUCTION) <= 0xFFU) + +#define IS_QSPI_ADDRESS_SIZE(ADDR_SIZE) (((ADDR_SIZE) == QSPI_ADDRESS_8_BITS) || \ + ((ADDR_SIZE) == QSPI_ADDRESS_16_BITS) || \ + ((ADDR_SIZE) == QSPI_ADDRESS_24_BITS) || \ + ((ADDR_SIZE) == QSPI_ADDRESS_32_BITS)) + +#define IS_QSPI_ALTERNATE_BYTES_SIZE(SIZE) (((SIZE) == QSPI_ALTERNATE_BYTES_8_BITS) || \ + ((SIZE) == QSPI_ALTERNATE_BYTES_16_BITS) || \ + ((SIZE) == QSPI_ALTERNATE_BYTES_24_BITS) || \ + ((SIZE) == QSPI_ALTERNATE_BYTES_32_BITS)) + +#define IS_QSPI_DUMMY_CYCLES(DCY) ((DCY) <= 31U) + +#define IS_QSPI_INSTRUCTION_MODE(MODE) (((MODE) == QSPI_INSTRUCTION_NONE) || \ + ((MODE) == QSPI_INSTRUCTION_1_LINE) || \ + ((MODE) == QSPI_INSTRUCTION_2_LINES) || \ + ((MODE) == QSPI_INSTRUCTION_4_LINES)) + +#define IS_QSPI_ADDRESS_MODE(MODE) (((MODE) == QSPI_ADDRESS_NONE) || \ + ((MODE) == QSPI_ADDRESS_1_LINE) || \ + ((MODE) == QSPI_ADDRESS_2_LINES) || \ + ((MODE) == QSPI_ADDRESS_4_LINES)) + +#define IS_QSPI_ALTERNATE_BYTES_MODE(MODE) (((MODE) == QSPI_ALTERNATE_BYTES_NONE) || \ + ((MODE) == QSPI_ALTERNATE_BYTES_1_LINE) || \ + ((MODE) == QSPI_ALTERNATE_BYTES_2_LINES) || \ + ((MODE) == QSPI_ALTERNATE_BYTES_4_LINES)) + +#define IS_QSPI_DATA_MODE(MODE) (((MODE) == QSPI_DATA_NONE) || \ + ((MODE) == QSPI_DATA_1_LINE) || \ + ((MODE) == QSPI_DATA_2_LINES) || \ + ((MODE) == QSPI_DATA_4_LINES)) + +#define IS_QSPI_DDR_MODE(DDR_MODE) (((DDR_MODE) == QSPI_DDR_MODE_DISABLE) || \ + ((DDR_MODE) == QSPI_DDR_MODE_ENABLE)) + +#define IS_QSPI_DDR_HHC(DDR_HHC) (((DDR_HHC) == QSPI_DDR_HHC_ANALOG_DELAY) || \ + ((DDR_HHC) == QSPI_DDR_HHC_HALF_CLK_DELAY)) + +#define IS_QSPI_SIOO_MODE(SIOO_MODE) (((SIOO_MODE) == QSPI_SIOO_INST_EVERY_CMD) || \ + ((SIOO_MODE) == QSPI_SIOO_INST_ONLY_FIRST_CMD)) + +#define IS_QSPI_INTERVAL(INTERVAL) ((INTERVAL) <= QUADSPI_PIR_INTERVAL) + +#define IS_QSPI_STATUS_BYTES_SIZE(SIZE) (((SIZE) >= 1U) && ((SIZE) <= 4U)) + +#define IS_QSPI_MATCH_MODE(MODE) (((MODE) == QSPI_MATCH_MODE_AND) || \ + ((MODE) == QSPI_MATCH_MODE_OR)) + +#define IS_QSPI_AUTOMATIC_STOP(APMS) (((APMS) == QSPI_AUTOMATIC_STOP_DISABLE) || \ + ((APMS) == QSPI_AUTOMATIC_STOP_ENABLE)) + +#define IS_QSPI_TIMEOUT_ACTIVATION(TCEN) (((TCEN) == QSPI_TIMEOUT_COUNTER_DISABLE) || \ + ((TCEN) == QSPI_TIMEOUT_COUNTER_ENABLE)) + +#define IS_QSPI_TIMEOUT_PERIOD(PERIOD) ((PERIOD) <= 0xFFFFU) +/** +* @} +*/ +/* End of private macros -----------------------------------------------------*/ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(QUADSPI) */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_QSPI_H */ diff --git a/libs/hal/stm32f4xx_hal_rcc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h similarity index 99% rename from libs/hal/stm32f4xx_hal_rcc.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h index dcf5814..3dafcd1 100644 --- a/libs/hal/stm32f4xx_hal_rcc.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc.h @@ -1407,7 +1407,7 @@ void HAL_RCC_CSSCallback(void); ((__SOURCE__) == RCC_RTCCLKSOURCE_HSE_DIV30) || \ ((__SOURCE__) == RCC_RTCCLKSOURCE_HSE_DIV31)) -#define IS_RCC_PLLM_VALUE(VALUE) ((VALUE) <= 63U) +#define IS_RCC_PLLM_VALUE(VALUE) ((2U <= (VALUE)) && ((VALUE) <= 63U)) #define IS_RCC_PLLP_VALUE(VALUE) (((VALUE) == 2U) || ((VALUE) == 4U) || ((VALUE) == 6U) || ((VALUE) == 8U)) diff --git a/libs/hal/stm32f4xx_hal_rcc_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h similarity index 99% rename from libs/hal/stm32f4xx_hal_rcc_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h index 909a717..bfba11f 100644 --- a/libs/hal/stm32f4xx_hal_rcc_ex.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rcc_ex.h @@ -526,7 +526,7 @@ typedef struct * @{ */ #define RCC_I2SCLKSOURCE_PLLI2S 0x00000000U -#define RCC_I2SCLKSOURCE_EXT 0x00000001U +#define RCC_I2SCLKSOURCE_EXT RCC_CFGR_I2SSRC /** * @} */ @@ -6101,7 +6101,7 @@ typedef struct * @arg RCC_I2SCLKSOURCE_EXT: External clock mapped on the I2S_CKIN pin * used as I2S clock source. */ -#define __HAL_RCC_I2S_CONFIG(__SOURCE__) (*(__IO uint32_t *) RCC_CFGR_I2SSRC_BB = (__SOURCE__)) +#define __HAL_RCC_I2S_CONFIG(__SOURCE__) (MODIFY_REG(RCC->CFGR, RCC_CFGR_I2SSRC, (__SOURCE__))) /** @brief Macro to get the I2S clock source (I2SCLK). diff --git a/libs/hal/stm32f4xx_hal_rng.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h similarity index 100% rename from libs/hal/stm32f4xx_hal_rng.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rng.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h new file mode 100644 index 0000000..6254ad6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc.h @@ -0,0 +1,922 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_rtc.h + * @author MCD Application Team + * @brief Header file of RTC HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 STM32F4xx_HAL_RTC_H +#define STM32F4xx_HAL_RTC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTC + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Types RTC Exported Types + * @{ + */ + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_RTC_STATE_RESET = 0x00U, /*!< RTC not yet initialized or disabled */ + HAL_RTC_STATE_READY = 0x01U, /*!< RTC initialized and ready for use */ + HAL_RTC_STATE_BUSY = 0x02U, /*!< RTC process is ongoing */ + HAL_RTC_STATE_TIMEOUT = 0x03U, /*!< RTC timeout state */ + HAL_RTC_STATE_ERROR = 0x04U /*!< RTC error state */ +} HAL_RTCStateTypeDef; + +/** + * @brief RTC Configuration Structure definition + */ +typedef struct +{ + uint32_t HourFormat; /*!< Specifies the RTC Hour Format. + This parameter can be a value of @ref RTC_Hour_Formats */ + + uint32_t AsynchPrediv; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F */ + + uint32_t SynchPrediv; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0x7FFF */ + + uint32_t OutPut; /*!< Specifies which signal will be routed to the RTC output. + This parameter can be a value of @ref RTC_Output_selection_Definitions */ + + uint32_t OutPutPolarity; /*!< Specifies the polarity of the output signal. + This parameter can be a value of @ref RTC_Output_Polarity_Definitions */ + + uint32_t OutPutType; /*!< Specifies the RTC Output Pin mode. + This parameter can be a value of @ref RTC_Output_Type_ALARM_OUT */ +} RTC_InitTypeDef; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint8_t Hours; /*!< Specifies the RTC Time Hour. + This parameter must be a number between Min_Data = 0 and Max_Data = 12 if the RTC_HourFormat_12 is selected + This parameter must be a number between Min_Data = 0 and Max_Data = 23 if the RTC_HourFormat_24 is selected */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 */ + + uint8_t TimeFormat; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_AM_PM_Definitions */ + + uint32_t SubSeconds; /*!< Specifies the RTC_SSR RTC Sub Second register content. + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity */ + + uint32_t SecondFraction; /*!< Specifies the range or granularity of Sub Second register content + corresponding to Synchronous prescaler factor value (PREDIV_S) + This parameter corresponds to a time unit range between [0-1] Second + with [1 Sec / SecondFraction +1] granularity. + This field will be used only by HAL_RTC_GetTime function */ + + uint32_t DayLightSaving; /*!< This interface is deprecated. To manage Daylight + Saving Time, please use HAL_RTC_DST_xxx functions */ + + uint32_t StoreOperation; /*!< This interface is deprecated. To manage Daylight + Saving Time, please use HAL_RTC_DST_xxx functions */ +} RTC_TimeTypeDef; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint8_t Month; /*!< Specifies the RTC Date Month (in BCD format). + This parameter can be a value of @ref RTC_Month_Date_Definitions */ + + uint8_t Date; /*!< Specifies the RTC Date. + This parameter must be a number between Min_Data = 1 and Max_Data = 31 */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be a number between Min_Data = 0 and Max_Data = 99 */ + +} RTC_DateTypeDef; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + RTC_TimeTypeDef AlarmTime; /*!< Specifies the RTC Alarm Time members */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_AlarmMask_Definitions */ + + uint32_t AlarmSubSecondMask; /*!< Specifies the RTC Alarm SubSeconds Masks. + This parameter can be a value of @ref RTC_Alarm_Sub_Seconds_Masks_Definitions */ + + uint32_t AlarmDateWeekDaySel; /*!< Specifies the RTC Alarm is on Date or WeekDay. + This parameter can be a value of @ref RTC_AlarmDateWeekDay_Definitions */ + + uint8_t AlarmDateWeekDay; /*!< Specifies the RTC Alarm Date/WeekDay. + If the Alarm Date is selected, this parameter must be set to a value in the 1-31 range. + If the Alarm WeekDay is selected, this parameter can be a value of @ref RTC_WeekDay_Definitions */ + + uint32_t Alarm; /*!< Specifies the alarm . + This parameter can be a value of @ref RTC_Alarms_Definitions */ +} RTC_AlarmTypeDef; + +/** + * @brief RTC Handle Structure definition + */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) +typedef struct __RTC_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ +{ + RTC_TypeDef *Instance; /*!< Register base address */ + + RTC_InitTypeDef Init; /*!< RTC required parameters */ + + HAL_LockTypeDef Lock; /*!< RTC locking object */ + + __IO HAL_RTCStateTypeDef State; /*!< Time communication state */ + +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + void (* AlarmAEventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Alarm A Event callback */ + + void (* AlarmBEventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Alarm B Event callback */ + + void (* TimeStampEventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Timestamp Event callback */ + + void (* WakeUpTimerEventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC WakeUpTimer Event callback */ + + void (* Tamper1EventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Tamper 1 Event callback */ + +#if defined(RTC_TAMPER2_SUPPORT) + void (* Tamper2EventCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Tamper 2 Event callback */ +#endif /* RTC_TAMPER2_SUPPORT */ + + void (* MspInitCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Msp Init callback */ + + void (* MspDeInitCallback) (struct __RTC_HandleTypeDef *hrtc); /*!< RTC Msp DeInit callback */ + +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + +} RTC_HandleTypeDef; + +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) +/** + * @brief HAL RTC Callback ID enumeration definition + */ +typedef enum +{ + HAL_RTC_ALARM_A_EVENT_CB_ID = 0x00U, /*!< RTC Alarm A Event Callback ID */ + HAL_RTC_ALARM_B_EVENT_CB_ID = 0x01U, /*!< RTC Alarm B Event Callback ID */ + HAL_RTC_TIMESTAMP_EVENT_CB_ID = 0x02U, /*!< RTC Timestamp Event Callback ID */ + HAL_RTC_WAKEUPTIMER_EVENT_CB_ID = 0x03U, /*!< RTC Wakeup Timer Event Callback ID */ + HAL_RTC_TAMPER1_EVENT_CB_ID = 0x04U, /*!< RTC Tamper 1 Callback ID */ +#if defined(RTC_TAMPER2_SUPPORT) + HAL_RTC_TAMPER2_EVENT_CB_ID = 0x05U, /*!< RTC Tamper 2 Callback ID */ +#endif /* RTC_TAMPER2_SUPPORT */ + HAL_RTC_MSPINIT_CB_ID = 0x0EU, /*!< RTC Msp Init callback ID */ + HAL_RTC_MSPDEINIT_CB_ID = 0x0FU /*!< RTC Msp DeInit callback ID */ +} HAL_RTC_CallbackIDTypeDef; + +/** + * @brief HAL RTC Callback pointer definition + */ +typedef void (*pRTC_CallbackTypeDef)(RTC_HandleTypeDef *hrtc); /*!< pointer to an RTC callback function */ +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Constants RTC Exported Constants + * @{ + */ + +/** @defgroup RTC_Hour_Formats RTC Hour Formats + * @{ + */ +#define RTC_HOURFORMAT_24 0x00000000U +#define RTC_HOURFORMAT_12 RTC_CR_FMT +/** + * @} + */ + +/** @defgroup RTC_Output_selection_Definitions RTC Output Selection Definitions + * @{ + */ +#define RTC_OUTPUT_DISABLE 0x00000000U +#define RTC_OUTPUT_ALARMA RTC_CR_OSEL_0 +#define RTC_OUTPUT_ALARMB RTC_CR_OSEL_1 +#define RTC_OUTPUT_WAKEUP RTC_CR_OSEL +/** + * @} + */ + +/** @defgroup RTC_Output_Polarity_Definitions RTC Output Polarity Definitions + * @{ + */ +#define RTC_OUTPUT_POLARITY_HIGH 0x00000000U +#define RTC_OUTPUT_POLARITY_LOW RTC_CR_POL +/** + * @} + */ + +/** @defgroup RTC_Output_Type_ALARM_OUT RTC Output Type ALARM OUT + * @{ + */ +#define RTC_OUTPUT_TYPE_OPENDRAIN 0x00000000U +#define RTC_OUTPUT_TYPE_PUSHPULL RTC_TAFCR_ALARMOUTTYPE +/** + * @} + */ + +/** @defgroup RTC_AM_PM_Definitions RTC AM PM Definitions + * @{ + */ +#define RTC_HOURFORMAT12_AM ((uint8_t)0x00) +#define RTC_HOURFORMAT12_PM ((uint8_t)0x01) +/** + * @} + */ + +/** @defgroup RTC_DayLightSaving_Definitions RTC DayLight Saving Definitions + * @{ + */ +#define RTC_DAYLIGHTSAVING_SUB1H RTC_CR_SUB1H +#define RTC_DAYLIGHTSAVING_ADD1H RTC_CR_ADD1H +#define RTC_DAYLIGHTSAVING_NONE 0x00000000U +/** + * @} + */ + +/** @defgroup RTC_StoreOperation_Definitions RTC Store Operation Definitions + * @{ + */ +#define RTC_STOREOPERATION_RESET 0x00000000U +#define RTC_STOREOPERATION_SET RTC_CR_BKP +/** + * @} + */ + +/** @defgroup RTC_Input_parameter_format_definitions RTC Input Parameter Format Definitions + * @{ + */ +#define RTC_FORMAT_BIN 0x00000000U +#define RTC_FORMAT_BCD 0x00000001U +/** + * @} + */ + +/** @defgroup RTC_Month_Date_Definitions RTC Month Date Definitions (in BCD format) + * @{ + */ +#define RTC_MONTH_JANUARY ((uint8_t)0x01) +#define RTC_MONTH_FEBRUARY ((uint8_t)0x02) +#define RTC_MONTH_MARCH ((uint8_t)0x03) +#define RTC_MONTH_APRIL ((uint8_t)0x04) +#define RTC_MONTH_MAY ((uint8_t)0x05) +#define RTC_MONTH_JUNE ((uint8_t)0x06) +#define RTC_MONTH_JULY ((uint8_t)0x07) +#define RTC_MONTH_AUGUST ((uint8_t)0x08) +#define RTC_MONTH_SEPTEMBER ((uint8_t)0x09) +#define RTC_MONTH_OCTOBER ((uint8_t)0x10) +#define RTC_MONTH_NOVEMBER ((uint8_t)0x11) +#define RTC_MONTH_DECEMBER ((uint8_t)0x12) +/** + * @} + */ + +/** @defgroup RTC_WeekDay_Definitions RTC WeekDay Definitions + * @{ + */ +#define RTC_WEEKDAY_MONDAY ((uint8_t)0x01) +#define RTC_WEEKDAY_TUESDAY ((uint8_t)0x02) +#define RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03) +#define RTC_WEEKDAY_THURSDAY ((uint8_t)0x04) +#define RTC_WEEKDAY_FRIDAY ((uint8_t)0x05) +#define RTC_WEEKDAY_SATURDAY ((uint8_t)0x06) +#define RTC_WEEKDAY_SUNDAY ((uint8_t)0x07) +/** + * @} + */ + +/** @defgroup RTC_AlarmDateWeekDay_Definitions RTC Alarm Date WeekDay Definitions + * @{ + */ +#define RTC_ALARMDATEWEEKDAYSEL_DATE 0x00000000U +#define RTC_ALARMDATEWEEKDAYSEL_WEEKDAY RTC_ALRMAR_WDSEL +/** + * @} + */ + +/** @defgroup RTC_AlarmMask_Definitions RTC Alarm Mask Definitions + * @{ + */ +#define RTC_ALARMMASK_NONE 0x00000000U +#define RTC_ALARMMASK_DATEWEEKDAY RTC_ALRMAR_MSK4 +#define RTC_ALARMMASK_HOURS RTC_ALRMAR_MSK3 +#define RTC_ALARMMASK_MINUTES RTC_ALRMAR_MSK2 +#define RTC_ALARMMASK_SECONDS RTC_ALRMAR_MSK1 +#define RTC_ALARMMASK_ALL (RTC_ALARMMASK_DATEWEEKDAY | \ + RTC_ALARMMASK_HOURS | \ + RTC_ALARMMASK_MINUTES | \ + RTC_ALARMMASK_SECONDS) +/** + * @} + */ + +/** @defgroup RTC_Alarms_Definitions RTC Alarms Definitions + * @{ + */ +#define RTC_ALARM_A RTC_CR_ALRAE +#define RTC_ALARM_B RTC_CR_ALRBE +/** + * @} + */ + +/** @defgroup RTC_Alarm_Sub_Seconds_Masks_Definitions RTC Alarm Sub Seconds Masks Definitions + * @{ + */ +/*!< All Alarm SS fields are masked. There is no comparison on sub seconds for Alarm */ +#define RTC_ALARMSUBSECONDMASK_ALL 0x00000000U +/*!< SS[14:1] are don't care in Alarm comparison. Only SS[0] is compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_1 RTC_ALRMASSR_MASKSS_0 +/*!< SS[14:2] are don't care in Alarm comparison. Only SS[1:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_2 RTC_ALRMASSR_MASKSS_1 +/*!< SS[14:3] are don't care in Alarm comparison. Only SS[2:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_3 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_1) +/*!< SS[14:4] are don't care in Alarm comparison. Only SS[3:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_4 RTC_ALRMASSR_MASKSS_2 +/*!< SS[14:5] are don't care in Alarm comparison. Only SS[4:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_5 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_2) +/*!< SS[14:6] are don't care in Alarm comparison. Only SS[5:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_6 (RTC_ALRMASSR_MASKSS_1 | RTC_ALRMASSR_MASKSS_2) +/*!< SS[14:7] are don't care in Alarm comparison. Only SS[6:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_7 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_1 | RTC_ALRMASSR_MASKSS_2) +/*!< SS[14:8] are don't care in Alarm comparison. Only SS[7:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_8 RTC_ALRMASSR_MASKSS_3 +/*!< SS[14:9] are don't care in Alarm comparison. Only SS[8:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_9 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14:10] are don't care in Alarm comparison. Only SS[9:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_10 (RTC_ALRMASSR_MASKSS_1 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14:11] are don't care in Alarm comparison. Only SS[10:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_11 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_1 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14:12] are don't care in Alarm comparison. Only SS[11:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_12 (RTC_ALRMASSR_MASKSS_2 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14:13] are don't care in Alarm comparison. Only SS[12:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14_13 (RTC_ALRMASSR_MASKSS_0 | RTC_ALRMASSR_MASKSS_2 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14] is don't care in Alarm comparison. Only SS[13:0] are compared. */ +#define RTC_ALARMSUBSECONDMASK_SS14 (RTC_ALRMASSR_MASKSS_1 | RTC_ALRMASSR_MASKSS_2 | RTC_ALRMASSR_MASKSS_3) +/*!< SS[14:0] are compared and must match to activate alarm. */ +#define RTC_ALARMSUBSECONDMASK_NONE RTC_ALRMASSR_MASKSS +/** + * @} + */ + +/** @defgroup RTC_Interrupts_Definitions RTC Interrupts Definitions + * @{ + */ +#define RTC_IT_TS RTC_CR_TSIE /*!< Enable Timestamp Interrupt */ +#define RTC_IT_WUT RTC_CR_WUTIE /*!< Enable Wakeup timer Interrupt */ +#define RTC_IT_ALRB RTC_CR_ALRBIE /*!< Enable Alarm B Interrupt */ +#define RTC_IT_ALRA RTC_CR_ALRAIE /*!< Enable Alarm A Interrupt */ +/** + * @} + */ + +/** @defgroup RTC_Flags_Definitions RTC Flags Definitions + * @{ + */ +#define RTC_FLAG_RECALPF RTC_ISR_RECALPF /*!< Recalibration pending flag */ +#if defined(RTC_TAMPER2_SUPPORT) +#define RTC_FLAG_TAMP2F RTC_ISR_TAMP2F /*!< Tamper 2 event flag */ +#endif /* RTC_TAMPER2_SUPPORT */ +#define RTC_FLAG_TAMP1F RTC_ISR_TAMP1F /*!< Tamper 1 event flag */ +#define RTC_FLAG_TSOVF RTC_ISR_TSOVF /*!< Timestamp overflow flag */ +#define RTC_FLAG_TSF RTC_ISR_TSF /*!< Timestamp event flag */ +#define RTC_FLAG_WUTF RTC_ISR_WUTF /*!< Wakeup timer event flag */ +#define RTC_FLAG_ALRBF RTC_ISR_ALRBF /*!< Alarm B event flag */ +#define RTC_FLAG_ALRAF RTC_ISR_ALRAF /*!< Alarm A event flag */ +#define RTC_FLAG_INITF RTC_ISR_INITF /*!< RTC in initialization mode flag */ +#define RTC_FLAG_RSF RTC_ISR_RSF /*!< Register synchronization flag */ +#define RTC_FLAG_INITS RTC_ISR_INITS /*!< RTC initialization status flag */ +#define RTC_FLAG_SHPF RTC_ISR_SHPF /*!< Shift operation pending flag */ +#define RTC_FLAG_WUTWF RTC_ISR_WUTWF /*!< WUTR register write allowance flag */ +#define RTC_FLAG_ALRBWF RTC_ISR_ALRBWF /*!< ALRMBR register write allowance flag */ +#define RTC_FLAG_ALRAWF RTC_ISR_ALRAWF /*!< ALRMAR register write allowance flag */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Macros RTC Exported Macros + * @{ + */ + +/** @brief Reset RTC handle state + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) +#define __HAL_RTC_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_RTC_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_RTC_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_RTC_STATE_RESET) +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + +/** + * @brief Disable the write protection for RTC registers. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_DISABLE(__HANDLE__) do { \ + (__HANDLE__)->Instance->WPR = 0xCAU; \ + (__HANDLE__)->Instance->WPR = 0x53U; \ + } while(0U) + +/** + * @brief Enable the write protection for RTC registers. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WRITEPROTECTION_ENABLE(__HANDLE__) do { \ + (__HANDLE__)->Instance->WPR = 0xFFU; \ + } while(0U) + + +/** + * @brief Check whether the RTC Calendar is initialized. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_IS_CALENDAR_INITIALIZED(__HANDLE__) (((((__HANDLE__)->Instance->ISR) & (RTC_FLAG_INITS)) == RTC_FLAG_INITS) ? 1U : 0U) + +/** + * @brief Enable the RTC ALARMA peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRAE)) + +/** + * @brief Disable the RTC ALARMA peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMA_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRAE)) + +/** + * @brief Enable the RTC ALARMB peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_ALRBE)) + +/** + * @brief Disable the RTC ALARMB peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_ALARMB_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_ALRBE)) + +/** + * @brief Enable the RTC Alarm interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Alarm interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Alarm interrupt sources to be enabled or disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Alarm interrupt has occurred or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Alarm interrupt to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__) >> 4U)) != 0U) ? 1U : 0U) + +/** + * @brief Get the selected RTC Alarm's flag status. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Alarm Flag to check. + * This parameter can be: + * @arg RTC_FLAG_ALRAF: Alarm A interrupt flag + * @arg RTC_FLAG_ALRAWF: Alarm A 'write allowed' flag + * @arg RTC_FLAG_ALRBF: Alarm B interrupt flag + * @arg RTC_FLAG_ALRBWF: Alarm B 'write allowed' flag + * @retval None + */ +#define __HAL_RTC_ALARM_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != 0U) ? 1U : 0U) + +/** + * @brief Clear the RTC Alarm's pending flags. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Alarm flag to be cleared. + * This parameter can be: + * @arg RTC_FLAG_ALRAF + * @arg RTC_FLAG_ALRBF + * @retval None + */ +#define __HAL_RTC_ALARM_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Check whether the specified RTC Alarm interrupt has been enabled or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Alarm interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_ALRA: Alarm A interrupt + * @arg RTC_IT_ALRB: Alarm B interrupt + * @retval None + */ +#define __HAL_RTC_ALARM_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != 0U) ? 1U : 0U) + +/** + * @brief Enable interrupt on the RTC Alarm associated EXTI line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_IT() (EXTI->IMR |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable interrupt on the RTC Alarm associated EXTI line. + * @retval None + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_IT() (EXTI->IMR &= ~RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Enable event on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_EVENT() (EXTI->EMR |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable event on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_EVENT() (EXTI->EMR &= ~RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Enable falling edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR &= ~RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Enable rising edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR |= RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR &= ~RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Enable rising & falling edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Disable rising & falling edge trigger on the RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_ALARM_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_ALARM_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Check whether the RTC Alarm associated EXTI line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_ALARM_EXTI_GET_FLAG() (EXTI->PR & RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Clear the RTC Alarm associated EXTI line flag. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_CLEAR_FLAG() (EXTI->PR = RTC_EXTI_LINE_ALARM_EVENT) + +/** + * @brief Generate a Software interrupt on RTC Alarm associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_ALARM_EXTI_GENERATE_SWIT() (EXTI->SWIER |= RTC_EXTI_LINE_ALARM_EVENT) +/** + * @} + */ + +/* Include RTC HAL Extended module */ +#include "stm32f4xx_hal_rtc_ex.h" + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup RTC_Exported_Functions + * @{ + */ + +/** @addtogroup RTC_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de-initialization functions ****************************/ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc); +void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group2 + * @{ + */ +/* RTC Time and Date functions ************************************************/ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group3 + * @{ + */ +/* RTC Alarm functions ********************************************************/ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format); +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm); +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format); +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group4 + * @{ + */ +/* Peripheral Control functions ***********************************************/ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc); + +/* RTC Daylight Saving Time functions *****************************************/ +void HAL_RTC_DST_Add1Hour(RTC_HandleTypeDef *hrtc); +void HAL_RTC_DST_Sub1Hour(RTC_HandleTypeDef *hrtc); +void HAL_RTC_DST_SetStoreOperation(RTC_HandleTypeDef *hrtc); +void HAL_RTC_DST_ClearStoreOperation(RTC_HandleTypeDef *hrtc); +uint32_t HAL_RTC_DST_ReadStoreOperation(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTC_Exported_Functions_Group5 + * @{ + */ +/* Peripheral State functions *************************************************/ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ + +/** @defgroup RTC_Private_Constants RTC Private Constants + * @{ + */ +/* Masks Definition */ +#define RTC_TR_RESERVED_MASK ((uint32_t)(RTC_TR_HT | RTC_TR_HU | \ + RTC_TR_MNT | RTC_TR_MNU | \ + RTC_TR_ST | RTC_TR_SU | \ + RTC_TR_PM)) +#define RTC_DR_RESERVED_MASK ((uint32_t)(RTC_DR_YT | RTC_DR_YU | \ + RTC_DR_MT | RTC_DR_MU | \ + RTC_DR_DT | RTC_DR_DU | \ + RTC_DR_WDU)) +#define RTC_INIT_MASK 0xFFFFFFFFU +#define RTC_RSF_MASK ((uint32_t)~(RTC_ISR_INIT | RTC_ISR_RSF)) +#define RTC_FLAGS_MASK ((uint32_t)(RTC_FLAG_INITF | RTC_FLAG_INITS | \ + RTC_FLAG_ALRAF | RTC_FLAG_ALRAWF | \ + RTC_FLAG_ALRBF | RTC_FLAG_ALRBWF | \ + RTC_FLAG_WUTF | RTC_FLAG_WUTWF | \ + RTC_FLAG_RECALPF | RTC_FLAG_SHPF | \ + RTC_FLAG_TSF | RTC_FLAG_TSOVF | \ + RTC_FLAG_RSF | RTC_TAMPER_FLAGS_MASK)) + +#define RTC_TIMEOUT_VALUE 1000U + +#define RTC_EXTI_LINE_ALARM_EVENT EXTI_IMR_MR17 /*!< External interrupt line 17 Connected to the RTC Alarm event */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ + +/** @defgroup RTC_Private_Macros RTC Private Macros + * @{ + */ + +/** @defgroup RTC_IS_RTC_Definitions RTC Private macros to check input parameters + * @{ + */ +#define IS_RTC_HOUR_FORMAT(FORMAT) (((FORMAT) == RTC_HOURFORMAT_12) || \ + ((FORMAT) == RTC_HOURFORMAT_24)) + +#define IS_RTC_OUTPUT(OUTPUT) (((OUTPUT) == RTC_OUTPUT_DISABLE) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMA) || \ + ((OUTPUT) == RTC_OUTPUT_ALARMB) || \ + ((OUTPUT) == RTC_OUTPUT_WAKEUP)) + +#define IS_RTC_OUTPUT_POL(POL) (((POL) == RTC_OUTPUT_POLARITY_HIGH) || \ + ((POL) == RTC_OUTPUT_POLARITY_LOW)) + +#define IS_RTC_OUTPUT_TYPE(TYPE) (((TYPE) == RTC_OUTPUT_TYPE_OPENDRAIN) || \ + ((TYPE) == RTC_OUTPUT_TYPE_PUSHPULL)) + +#define IS_RTC_ASYNCH_PREDIV(PREDIV) ((PREDIV) <= 0x7FU) +#define IS_RTC_SYNCH_PREDIV(PREDIV) ((PREDIV) <= 0x7FFFU) + +#define IS_RTC_HOUR12(HOUR) (((HOUR) > 0U) && ((HOUR) <= 12U)) +#define IS_RTC_HOUR24(HOUR) ((HOUR) <= 23U) +#define IS_RTC_MINUTES(MINUTES) ((MINUTES) <= 59U) +#define IS_RTC_SECONDS(SECONDS) ((SECONDS) <= 59U) + +#define IS_RTC_HOURFORMAT12(PM) (((PM) == RTC_HOURFORMAT12_AM) || \ + ((PM) == RTC_HOURFORMAT12_PM)) + +#define IS_RTC_DAYLIGHT_SAVING(SAVE) (((SAVE) == RTC_DAYLIGHTSAVING_SUB1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_ADD1H) || \ + ((SAVE) == RTC_DAYLIGHTSAVING_NONE)) + +#define IS_RTC_STORE_OPERATION(OPERATION) (((OPERATION) == RTC_STOREOPERATION_RESET) || \ + ((OPERATION) == RTC_STOREOPERATION_SET)) + +#define IS_RTC_FORMAT(FORMAT) (((FORMAT) == RTC_FORMAT_BIN) || ((FORMAT) == RTC_FORMAT_BCD)) + +#define IS_RTC_YEAR(YEAR) ((YEAR) <= 99U) +#define IS_RTC_MONTH(MONTH) (((MONTH) >= 1U) && ((MONTH) <= 12U)) +#define IS_RTC_DATE(DATE) (((DATE) >= 1U) && ((DATE) <= 31U)) + +#define IS_RTC_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_DATE(DATE) (((DATE) > 0U) && ((DATE) <= 31U)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(WEEKDAY) (((WEEKDAY) == RTC_WEEKDAY_MONDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_TUESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_WEDNESDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_THURSDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_FRIDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SATURDAY) || \ + ((WEEKDAY) == RTC_WEEKDAY_SUNDAY)) + +#define IS_RTC_ALARM_DATE_WEEKDAY_SEL(SEL) (((SEL) == RTC_ALARMDATEWEEKDAYSEL_DATE) || \ + ((SEL) == RTC_ALARMDATEWEEKDAYSEL_WEEKDAY)) + +#define IS_RTC_ALARM_MASK(MASK) (((MASK) & ((uint32_t)~RTC_ALARMMASK_ALL)) == 0U) + +#define IS_RTC_ALARM(ALARM) (((ALARM) == RTC_ALARM_A) || ((ALARM) == RTC_ALARM_B)) + +#define IS_RTC_ALARM_SUB_SECOND_VALUE(VALUE) ((VALUE) <= RTC_ALRMASSR_SS) + +#define IS_RTC_ALARM_SUB_SECOND_MASK(MASK) (((MASK) == RTC_ALARMSUBSECONDMASK_ALL) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_1) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_2) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_3) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_4) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_5) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_6) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_7) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_8) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_9) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_10) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_11) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_12) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14_13) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_SS14) || \ + ((MASK) == RTC_ALARMSUBSECONDMASK_NONE)) +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup RTC_Private_Functions RTC Private Functions + * @{ + */ +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc); +uint8_t RTC_ByteToBcd2(uint8_t number); +uint8_t RTC_Bcd2ToByte(uint8_t number); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_RTC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h new file mode 100644 index 0000000..ff5f14d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_rtc_ex.h @@ -0,0 +1,1079 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_rtc_ex.h + * @author MCD Application Team + * @brief Header file of RTC HAL Extended module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 STM32F4xx_HAL_RTC_EX_H +#define STM32F4xx_HAL_RTC_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ + +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup RTCEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Types RTCEx Exported Types + * @{ + */ + +/** + * @brief RTC Tamper structure definition + */ +typedef struct +{ + uint32_t Tamper; /*!< Specifies the Tamper Pin. + This parameter can be a value of @ref RTCEx_Tamper_Pin_Definitions */ + + uint32_t PinSelection; /*!< Specifies the Tamper Pin. + This parameter can be a value of @ref RTCEx_Tamper_Pin_Selection */ + + uint32_t Trigger; /*!< Specifies the Tamper Trigger. + This parameter can be a value of @ref RTCEx_Tamper_Trigger_Definitions */ + + uint32_t Filter; /*!< Specifies the RTC Filter Tamper. + This parameter can be a value of @ref RTCEx_Tamper_Filter_Definitions */ + + uint32_t SamplingFrequency; /*!< Specifies the sampling frequency. + This parameter can be a value of @ref RTCEx_Tamper_Sampling_Frequencies_Definitions */ + + uint32_t PrechargeDuration; /*!< Specifies the Precharge Duration . + This parameter can be a value of @ref RTCEx_Tamper_Pin_Precharge_Duration_Definitions */ + + uint32_t TamperPullUp; /*!< Specifies the Tamper PullUp . + This parameter can be a value of @ref RTCEx_Tamper_Pull_Up_Definitions */ + + uint32_t TimeStampOnTamperDetection; /*!< Specifies the TimeStampOnTamperDetection. + This parameter can be a value of @ref RTCEx_Tamper_TimeStampOnTamperDetection_Definitions */ +} RTC_TamperTypeDef; +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Constants RTCEx Exported Constants + * @{ + */ + +/** @defgroup RTCEx_Backup_Registers_Definitions RTCEx Backup Registers Definitions + * @{ + */ +#define RTC_BKP_DR0 0x00000000U +#define RTC_BKP_DR1 0x00000001U +#define RTC_BKP_DR2 0x00000002U +#define RTC_BKP_DR3 0x00000003U +#define RTC_BKP_DR4 0x00000004U +#define RTC_BKP_DR5 0x00000005U +#define RTC_BKP_DR6 0x00000006U +#define RTC_BKP_DR7 0x00000007U +#define RTC_BKP_DR8 0x00000008U +#define RTC_BKP_DR9 0x00000009U +#define RTC_BKP_DR10 0x0000000AU +#define RTC_BKP_DR11 0x0000000BU +#define RTC_BKP_DR12 0x0000000CU +#define RTC_BKP_DR13 0x0000000DU +#define RTC_BKP_DR14 0x0000000EU +#define RTC_BKP_DR15 0x0000000FU +#define RTC_BKP_DR16 0x00000010U +#define RTC_BKP_DR17 0x00000011U +#define RTC_BKP_DR18 0x00000012U +#define RTC_BKP_DR19 0x00000013U +/** + * @} + */ + +/** @defgroup RTCEx_Timestamp_Edges_Definitions RTCEx Timestamp Edges Definitions + * @{ + */ +#define RTC_TIMESTAMPEDGE_RISING 0x00000000U +#define RTC_TIMESTAMPEDGE_FALLING RTC_CR_TSEDGE +/** + * @} + */ + +/** @defgroup RTCEx_Timestamp_Pin_Selection RTC Timestamp Pin Selection + * @{ + */ +#define RTC_TIMESTAMPPIN_DEFAULT 0x00000000U +#if defined(RTC_AF2_SUPPORT) +#define RTC_TIMESTAMPPIN_POS1 RTC_TAFCR_TSINSEL +#endif /* RTC_AF2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pin_Definitions RTCEx Tamper Pins Definitions + * @{ + */ +#define RTC_TAMPER_1 RTC_TAFCR_TAMP1E +#if defined(RTC_TAMPER2_SUPPORT) +#define RTC_TAMPER_2 RTC_TAFCR_TAMP2E +#endif /* RTC_TAMPER2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pin_Selection RTC tamper Pins Selection + * @{ + */ +#define RTC_TAMPERPIN_DEFAULT 0x00000000U +#if defined(RTC_AF2_SUPPORT) +#define RTC_TAMPERPIN_POS1 RTC_TAFCR_TAMP1INSEL +#endif /* RTC_AF2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Interrupt_Definitions RTCEx Tamper Interrupt Definitions + * @{ + */ +#define RTC_IT_TAMP RTC_TAFCR_TAMPIE /*!< Enable global Tamper Interrupt */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Trigger_Definitions RTCEx Tamper Triggers Definitions + * @{ + */ +#define RTC_TAMPERTRIGGER_RISINGEDGE 0x00000000U +#define RTC_TAMPERTRIGGER_FALLINGEDGE RTC_TAFCR_TAMP1TRG +#define RTC_TAMPERTRIGGER_LOWLEVEL RTC_TAMPERTRIGGER_RISINGEDGE +#define RTC_TAMPERTRIGGER_HIGHLEVEL RTC_TAMPERTRIGGER_FALLINGEDGE +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Filter_Definitions RTCEx Tamper Filter Definitions + * @{ + */ +#define RTC_TAMPERFILTER_DISABLE 0x00000000U /*!< Tamper filter is disabled */ + +#define RTC_TAMPERFILTER_2SAMPLE RTC_TAFCR_TAMPFLT_0 /*!< Tamper is activated after 2 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_4SAMPLE RTC_TAFCR_TAMPFLT_1 /*!< Tamper is activated after 4 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_8SAMPLE RTC_TAFCR_TAMPFLT /*!< Tamper is activated after 8 + consecutive samples at the active level */ +#define RTC_TAMPERFILTER_MASK RTC_TAFCR_TAMPFLT /*!< Masking all bits except those of + field TAMPFLT */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Sampling_Frequencies_Definitions RTCEx Tamper Sampling Frequencies Definitions + * @{ + */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768 0x00000000U /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 32768 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384 RTC_TAFCR_TAMPFREQ_0 /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 16384 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192 RTC_TAFCR_TAMPFREQ_1 /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 8192 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096 (RTC_TAFCR_TAMPFREQ_0 | RTC_TAFCR_TAMPFREQ_1) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 4096 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048 RTC_TAFCR_TAMPFREQ_2 /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 2048 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024 (RTC_TAFCR_TAMPFREQ_0 | RTC_TAFCR_TAMPFREQ_2) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 1024 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512 (RTC_TAFCR_TAMPFREQ_1 | RTC_TAFCR_TAMPFREQ_2) /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 512 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256 RTC_TAFCR_TAMPFREQ /*!< Each of the tamper inputs are sampled + with a frequency = RTCCLK / 256 */ +#define RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK RTC_TAFCR_TAMPFREQ /*!< Masking all bits except those of + field TAMPFREQ */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pin_Precharge_Duration_Definitions RTCEx Tamper Pin Precharge Duration Definitions + * @{ + */ +#define RTC_TAMPERPRECHARGEDURATION_1RTCCLK 0x00000000U /*!< Tamper pins are pre-charged before + sampling during 1 RTCCLK cycle */ +#define RTC_TAMPERPRECHARGEDURATION_2RTCCLK RTC_TAFCR_TAMPPRCH_0 /*!< Tamper pins are pre-charged before + sampling during 2 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_4RTCCLK RTC_TAFCR_TAMPPRCH_1 /*!< Tamper pins are pre-charged before + sampling during 4 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_8RTCCLK RTC_TAFCR_TAMPPRCH /*!< Tamper pins are pre-charged before + sampling during 8 RTCCLK cycles */ +#define RTC_TAMPERPRECHARGEDURATION_MASK RTC_TAFCR_TAMPPRCH /*!< Masking all bits except those of + field TAMPPRCH */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_Pull_Up_Definitions RTCEx Tamper Pull Up Definitions + * @{ + */ +#define RTC_TAMPER_PULLUP_ENABLE 0x00000000U /*!< Tamper pins are pre-charged before sampling */ +#define RTC_TAMPER_PULLUP_DISABLE RTC_TAFCR_TAMPPUDIS /*!< Tamper pins are not pre-charged before sampling */ +#define RTC_TAMPER_PULLUP_MASK RTC_TAFCR_TAMPPUDIS /*!< Masking all bits except bit TAMPPUDIS */ +/** + * @} + */ + +/** @defgroup RTCEx_Tamper_TimeStampOnTamperDetection_Definitions RTCEx Tamper TimeStamp On Tamper Detection Definitions + * @{ + */ +#define RTC_TIMESTAMPONTAMPERDETECTION_ENABLE RTC_TAFCR_TAMPTS /*!< TimeStamp on Tamper Detection event saved */ +#define RTC_TIMESTAMPONTAMPERDETECTION_DISABLE 0x00000000U /*!< TimeStamp on Tamper Detection event is not saved */ +#define RTC_TIMESTAMPONTAMPERDETECTION_MASK RTC_TAFCR_TAMPTS /*!< Masking all bits except bit TAMPTS */ +/** + * @} + */ + +/** @defgroup RTCEx_Wakeup_Timer_Definitions RTCEx Wakeup Timer Definitions + * @{ + */ +#define RTC_WAKEUPCLOCK_RTCCLK_DIV16 0x00000000U +#define RTC_WAKEUPCLOCK_RTCCLK_DIV8 RTC_CR_WUCKSEL_0 +#define RTC_WAKEUPCLOCK_RTCCLK_DIV4 RTC_CR_WUCKSEL_1 +#define RTC_WAKEUPCLOCK_RTCCLK_DIV2 (RTC_CR_WUCKSEL_0 | RTC_CR_WUCKSEL_1) +#define RTC_WAKEUPCLOCK_CK_SPRE_16BITS RTC_CR_WUCKSEL_2 +#define RTC_WAKEUPCLOCK_CK_SPRE_17BITS (RTC_CR_WUCKSEL_1 | RTC_CR_WUCKSEL_2) +/** + * @} + */ + +/** @defgroup RTCEx_Coarse_Calibration_Definitions RTCEx Coarse Calib Definitions + * @{ + */ +#define RTC_CALIBSIGN_POSITIVE 0x00000000U +#define RTC_CALIBSIGN_NEGATIVE RTC_CALIBR_DCS +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_period_Definitions RTCEx Smooth Calib Period Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PERIOD_32SEC 0x00000000U /*!< If RTCCLK = 32768 Hz, smooth calibration + period is 32s, otherwise 2^20 RTCCLK pulses */ +#define RTC_SMOOTHCALIB_PERIOD_16SEC RTC_CALR_CALW16 /*!< If RTCCLK = 32768 Hz, smooth calibration + period is 16s, otherwise 2^19 RTCCLK pulses */ +#define RTC_SMOOTHCALIB_PERIOD_8SEC RTC_CALR_CALW8 /*!< If RTCCLK = 32768 Hz, smooth calibration + period is 8s, otherwise 2^18 RTCCLK pulses */ +/** + * @} + */ + +/** @defgroup RTCEx_Smooth_calib_Plus_pulses_Definitions RTCEx Smooth Calib Plus Pulses Definitions + * @{ + */ +#define RTC_SMOOTHCALIB_PLUSPULSES_SET RTC_CALR_CALP /*!< The number of RTCCLK pulses added + during a X -second window = Y - CALM[8:0] + with Y = 512, 256, 128 when X = 32, 16, 8 */ +#define RTC_SMOOTHCALIB_PLUSPULSES_RESET 0x00000000U /*!< The number of RTCCLK pulses subbstited + during a 32-second window = CALM[8:0] */ +/** + * @} + */ + +/** @defgroup RTCEx_Add_1_Second_Parameter_Definitions RTCEx Add 1 Second Parameter Definitions + * @{ + */ +#define RTC_SHIFTADD1S_RESET 0x00000000U +#define RTC_SHIFTADD1S_SET RTC_SHIFTR_ADD1S +/** + * @} + */ + +/** @defgroup RTCEx_Calib_Output_selection_Definitions RTCEx Calib Output Selection Definitions + * @{ + */ +#define RTC_CALIBOUTPUT_512HZ 0x00000000U +#define RTC_CALIBOUTPUT_1HZ RTC_CR_COSEL +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Macros RTCEx Exported Macros + * @{ + */ + +/* ---------------------------------WAKEUPTIMER-------------------------------*/ + +/** @defgroup RTCEx_WakeUp_Timer RTCEx WakeUp Timer + * @{ + */ + +/** + * @brief Enable the RTC WakeUp Timer peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_WUTE)) + +/** + * @brief Disable the RTC Wakeup Timer peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_WUTE)) + +/** + * @brief Enable the RTC Wakeup Timer interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Wakeup Timer interrupt sources to be enabled or disabled. + * This parameter can be: + * @arg RTC_IT_WUT: Wakeup Timer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Wakeup Timer interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Wakeup Timer interrupt sources to be enabled or disabled. + * This parameter can be: + * @arg RTC_IT_WUT: Wakeup Timer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Wakeup Timer interrupt has occurred or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Wakeup Timer interrupt to check. + * This parameter can be: + * @arg RTC_IT_WUT: Wakeup Timer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__) >> 4U)) != 0U) ? 1U : 0U) + +/** + * @brief Check whether the specified RTC Wakeup timer interrupt has been enabled or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Wakeup timer interrupt sources to check. + * This parameter can be: + * @arg RTC_IT_WUT: WakeUpTimer interrupt + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != 0U) ? 1U : 0U) + +/** + * @brief Get the selected RTC Wakeup Timer's flag status. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Wakeup Timer flag to check. + * This parameter can be: + * @arg RTC_FLAG_WUTF: Wakeup Timer interrupt flag + * @arg RTC_FLAG_WUTWF: Wakeup Timer 'write allowed' flag + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != 0U)? 1U : 0U) + +/** + * @brief Clear the RTC Wakeup timer's pending flags. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Wakeup Timer Flag to clear. + * This parameter can be: + * @arg RTC_FLAG_WUTF: Wakeup Timer interrupt Flag + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @brief Enable interrupt on the RTC Wakeup Timer associated EXTI line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT() (EXTI->IMR |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable interrupt on the RTC Wakeup Timer associated EXTI line. + * @retval None + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_IT() (EXTI->IMR &= ~RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable event on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_EVENT() (EXTI->EMR |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable event on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_EVENT() (EXTI->EMR &= ~RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable falling edge trigger on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR &= ~RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable rising edge trigger on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR &= ~RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Enable rising & falling edge trigger on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Disable rising & falling edge trigger on the RTC Wakeup Timer associated EXTI line. + * This parameter can be: + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Check whether the RTC Wakeup Timer associated EXTI line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GET_FLAG() (EXTI->PR & RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Clear the RTC Wakeup Timer associated EXTI line flag. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG() (EXTI->PR = RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC Wakeup Timer associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_WAKEUPTIMER_EXTI_GENERATE_SWIT() (EXTI->SWIER |= RTC_EXTI_LINE_WAKEUPTIMER_EVENT) + +/** + * @} + */ + +/* ---------------------------------TIMESTAMP---------------------------------*/ + +/** @defgroup RTCEx_Timestamp RTCEx Timestamp + * @{ + */ + +/** + * @brief Enable the RTC Timestamp peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_TSE)) + +/** + * @brief Disable the RTC Timestamp peripheral. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_TSE)) + +/** + * @brief Enable the RTC Timestamp interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Timestamp interrupt sources to be enabled or disabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Timestamp interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Timestamp interrupt sources to be enabled or disabled. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Timestamp interrupt has occurred or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Timestamp interrupt to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__) >> 4U)) != 0U) ? 1U : 0U) + +/** + * @brief Check whether the specified RTC Timestamp interrupt has been enabled or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Timestamp interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TS: TimeStamp interrupt + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->CR) & (__INTERRUPT__)) != 0U) ? 1U : 0U) + +/** + * @brief Get the selected RTC Timestamp's flag status. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Timestamp flag to check. + * This parameter can be: + * @arg RTC_FLAG_TSF: Timestamp interrupt flag + * @arg RTC_FLAG_TSOVF: Timestamp overflow flag + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != 0U)? 1U : 0U) + +/** + * @brief Clear the RTC Timestamp's pending flags. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Timestamp flag to clear. + * This parameter can be: + * @arg RTC_FLAG_TSF: Timestamp interrupt flag + * @arg RTC_FLAG_TSOVF: Timestamp overflow flag + * @retval None + */ +#define __HAL_RTC_TIMESTAMP_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) + +/** + * @} + */ + +/* ---------------------------------TAMPER------------------------------------*/ + +/** @defgroup RTCEx_Tamper RTCEx Tamper + * @{ + */ + +/** + * @brief Enable the RTC Tamper1 input detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAFCR |= (RTC_TAFCR_TAMP1E)) + +/** + * @brief Disable the RTC Tamper1 input detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER1_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAFCR &= ~(RTC_TAFCR_TAMP1E)) + +#if defined(RTC_TAMPER2_SUPPORT) +/** + * @brief Enable the RTC Tamper2 input detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->TAFCR |= (RTC_TAFCR_TAMP2E)) + +/** + * @brief Disable the RTC Tamper2 input detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_TAMPER2_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->TAFCR &= ~(RTC_TAFCR_TAMP2E)) +#endif /* RTC_TAMPER2_SUPPORT */ + +/** + * @brief Enable the RTC Tamper interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Tamper interrupt sources to be enabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: Tamper global interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAFCR |= (__INTERRUPT__)) + +/** + * @brief Disable the RTC Tamper interrupt. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Tamper interrupt sources to be disabled. + * This parameter can be any combination of the following values: + * @arg RTC_IT_TAMP: Tamper global interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->TAFCR &= ~(__INTERRUPT__)) + +/** + * @brief Check whether the specified RTC Tamper interrupt has occurred or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Tamper interrupt to check. + * This parameter can be: + * @arg RTC_IT_TAMP1: Tamper 1 interrupt + * @arg RTC_IT_TAMP2: Tamper 2 interrupt + * @note RTC_IT_TAMP2 is not applicable to all devices. + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_IT(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->ISR) & ((__INTERRUPT__) >> 4U)) != 0U) ? 1U : 0U) + +/** + * @brief Check whether the specified RTC Tamper interrupt has been enabled or not. + * @param __HANDLE__ specifies the RTC handle. + * @param __INTERRUPT__ specifies the RTC Tamper interrupt source to check. + * This parameter can be: + * @arg RTC_IT_TAMP: Tamper global interrupt + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((((__HANDLE__)->Instance->TAFCR) & (__INTERRUPT__)) != 0U) ? 1U : 0U) + +/** + * @brief Get the selected RTC Tamper's flag status. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Tamper flag to be checked. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper 1 interrupt flag + * @arg RTC_FLAG_TAMP2F: Tamper 2 interrupt flag + * @note RTC_FLAG_TAMP2F is not applicable to all devices. + * @retval None + */ +#define __HAL_RTC_TAMPER_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != 0U)? 1U : 0U) + +/** + * @brief Clear the RTC Tamper's pending flags. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC Tamper Flag to clear. + * This parameter can be: + * @arg RTC_FLAG_TAMP1F: Tamper 1 interrupt flag + * @arg RTC_FLAG_TAMP2F: Tamper 2 interrupt flag + * @note RTC_FLAG_TAMP2F is not applicable to all devices. + * @retval None + */ +#define __HAL_RTC_TAMPER_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ISR) = (~((__FLAG__) | RTC_ISR_INIT)|((__HANDLE__)->Instance->ISR & RTC_ISR_INIT)) +/** + * @} + */ + +/* --------------------------TAMPER/TIMESTAMP---------------------------------*/ +/** @defgroup RTCEx_Tamper_Timestamp EXTI RTC Tamper Timestamp EXTI + * @{ + */ + +/** + * @brief Enable interrupt on the RTC Tamper and Timestamp associated EXTI line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT() (EXTI->IMR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable interrupt on the RTC Tamper and Timestamp associated EXTI line. + * @retval None + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_IT() (EXTI->IMR &= ~RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Enable event on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_EVENT() (EXTI->EMR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable event on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_EVENT() (EXTI->EMR &= ~RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Enable falling edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE() (EXTI->FTSR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable falling edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE() (EXTI->FTSR &= ~RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Enable rising edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE() (EXTI->RTSR |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Disable rising edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE() (EXTI->RTSR &= ~RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Enable rising & falling edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Disable rising & falling edge trigger on the RTC Tamper and Timestamp associated EXTI line. + * This parameter can be: + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_FALLING_EDGE() do { \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_RISING_EDGE(); \ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_DISABLE_FALLING_EDGE(); \ + } while(0U) + +/** + * @brief Check whether the RTC Tamper and Timestamp associated EXTI line interrupt flag is set or not. + * @retval Line Status. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG() (EXTI->PR & RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Clear the RTC Tamper and Timestamp associated EXTI line flag. + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG() (EXTI->PR = RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) + +/** + * @brief Generate a Software interrupt on the RTC Tamper and Timestamp associated EXTI line + * @retval None. + */ +#define __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GENERATE_SWIT() (EXTI->SWIER |= RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT) +/** + * @} + */ + +/* ------------------------------CALIBRATION----------------------------------*/ + +/** @defgroup RTCEx_Calibration RTCEx Calibration + * @{ + */ + +/** + * @brief Enable the Coarse calibration process. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_COARSE_CALIB_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_DCE)) + +/** + * @brief Disable the Coarse calibration process. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_COARSE_CALIB_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_DCE)) + +/** + * @brief Enable the RTC calibration output. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_COE)) + +/** + * @brief Disable the calibration output. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_COE)) + +/** + * @brief Enable the clock reference detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR |= (RTC_CR_REFCKON)) + +/** + * @brief Disable the clock reference detection. + * @param __HANDLE__ specifies the RTC handle. + * @retval None + */ +#define __HAL_RTC_CLOCKREF_DETECTION_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= ~(RTC_CR_REFCKON)) + +/** + * @brief Get the selected RTC shift operation's flag status. + * @param __HANDLE__ specifies the RTC handle. + * @param __FLAG__ specifies the RTC shift operation Flag is pending or not. + * This parameter can be: + * @arg RTC_FLAG_SHPF: Shift pending flag + * @retval None + */ +#define __HAL_RTC_SHIFT_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->ISR) & (__FLAG__)) != 0U)? 1U : 0U) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions + * @{ + */ + +/** @addtogroup RTCEx_Exported_Functions_Group1 + * @{ + */ +/* RTC Timestamp and Tamper functions *****************************************/ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format); + +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper); +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper); +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper); +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc); + +void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc); +#if defined(RTC_TAMPER2_SUPPORT) +void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc); +#endif /* RTC_TAMPER2_SUPPORT */ +void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#if defined(RTC_TAMPER2_SUPPORT) +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +#endif /* RTC_TAMPER2_SUPPORT */ +/** + * @} + */ + +/** @addtogroup RTCEx_Exported_Functions_Group2 + * @{ + */ +/* RTC Wakeup functions ******************************************************/ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock); +HAL_StatusTypeDef HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc); +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc); +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/** @addtogroup RTCEx_Exported_Functions_Group3 + * @{ + */ +/* Extended Control functions ************************************************/ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data); +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister); + +HAL_StatusTypeDef HAL_RTCEx_SetCoarseCalib(RTC_HandleTypeDef *hrtc, uint32_t CalibSign, uint32_t Value); +HAL_StatusTypeDef HAL_RTCEx_DeactivateCoarseCalib(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue); +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef *hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS); +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef *hrtc, uint32_t CalibOutput); +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef *hrtc); +/** + * @} + */ + +/** @addtogroup RTCEx_Exported_Functions_Group4 + * @{ + */ +/* Extended RTC features functions *******************************************/ +void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc); +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout); +/** + * @} + */ + +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ + +/** @defgroup RTCEx_Private_Constants RTCEx Private Constants + * @{ + */ +#define RTC_EXTI_LINE_TAMPER_TIMESTAMP_EVENT EXTI_IMR_MR21 /*!< External interrupt line 21 Connected to the RTC Tamper and Timestamp event */ +#define RTC_EXTI_LINE_WAKEUPTIMER_EVENT EXTI_IMR_MR22 /*!< External interrupt line 22 Connected to the RTC Wakeup event */ +/** + * @} + */ + +/** @defgroup RTCEx_Private_Constants RTCEx Private Constants + * @{ + */ +/* Masks Definition */ +#if defined(RTC_TAMPER2_SUPPORT) +#define RTC_TAMPER_ENABLE_BITS_MASK ((uint32_t) (RTC_TAMPER_1 | \ + RTC_TAMPER_2)) + +#define RTC_TAMPER_FLAGS_MASK ((uint32_t) (RTC_FLAG_TAMP1F | \ + RTC_FLAG_TAMP2F)) +#else /* RTC_TAMPER2_SUPPORT */ +#define RTC_TAMPER_ENABLE_BITS_MASK RTC_TAMPER_1 + +#define RTC_TAMPER_FLAGS_MASK RTC_FLAG_TAMP1F +#endif /* RTC_TAMPER2_SUPPORT */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ + +/** @defgroup RTCEx_Private_Macros RTCEx Private Macros + * @{ + */ + +/** @defgroup RTCEx_IS_RTC_Definitions Private macros to check input parameters + * @{ + */ +#define IS_RTC_BKP(BKP) ((BKP) < (uint32_t) RTC_BKP_NUMBER) + +#define IS_TIMESTAMP_EDGE(EDGE) (((EDGE) == RTC_TIMESTAMPEDGE_RISING) || \ + ((EDGE) == RTC_TIMESTAMPEDGE_FALLING)) + +#define IS_RTC_TAMPER(TAMPER) ((((TAMPER) & ((uint32_t)~RTC_TAMPER_ENABLE_BITS_MASK)) == 0x00U) && ((TAMPER) != 0U)) + +#if defined(RTC_AF2_SUPPORT) +#define IS_RTC_TAMPER_PIN(PIN) (((PIN) == RTC_TAMPERPIN_DEFAULT) || \ + ((PIN) == RTC_TAMPERPIN_POS1)) +#else /* RTC_AF2_SUPPORT */ +#define IS_RTC_TAMPER_PIN(PIN) ((PIN) == RTC_TAMPERPIN_DEFAULT) +#endif /* RTC_AF2_SUPPORT */ + +#if defined(RTC_AF2_SUPPORT) +#define IS_RTC_TIMESTAMP_PIN(PIN) (((PIN) == RTC_TIMESTAMPPIN_DEFAULT) || \ + ((PIN) == RTC_TIMESTAMPPIN_POS1)) +#else /* RTC_AF2_SUPPORT */ +#define IS_RTC_TIMESTAMP_PIN(PIN) ((PIN) == RTC_TIMESTAMPPIN_DEFAULT) +#endif /* RTC_AF2_SUPPORT */ + +#define IS_RTC_TAMPER_TRIGGER(TRIGGER) (((TRIGGER) == RTC_TAMPERTRIGGER_RISINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_FALLINGEDGE) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_LOWLEVEL) || \ + ((TRIGGER) == RTC_TAMPERTRIGGER_HIGHLEVEL)) + +#define IS_RTC_TAMPER_FILTER(FILTER) (((FILTER) == RTC_TAMPERFILTER_DISABLE) || \ + ((FILTER) == RTC_TAMPERFILTER_2SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_4SAMPLE) || \ + ((FILTER) == RTC_TAMPERFILTER_8SAMPLE)) + +#define IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(FILTER, TRIGGER) \ + ( ( ((FILTER) != RTC_TAMPERFILTER_DISABLE) \ + && ( ((TRIGGER) == RTC_TAMPERTRIGGER_LOWLEVEL) \ + || ((TRIGGER) == RTC_TAMPERTRIGGER_HIGHLEVEL))) \ + || ( ((FILTER) == RTC_TAMPERFILTER_DISABLE) \ + && ( ((TRIGGER) == RTC_TAMPERTRIGGER_RISINGEDGE) \ + || ((TRIGGER) == RTC_TAMPERTRIGGER_FALLINGEDGE)))) + +#define IS_RTC_TAMPER_SAMPLING_FREQ(FREQ) (((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV32768)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV16384)|| \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV8192) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV4096) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV2048) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV1024) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV512) || \ + ((FREQ) == RTC_TAMPERSAMPLINGFREQ_RTCCLK_DIV256)) + +#define IS_RTC_TAMPER_PRECHARGE_DURATION(DURATION) (((DURATION) == RTC_TAMPERPRECHARGEDURATION_1RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_2RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_4RTCCLK) || \ + ((DURATION) == RTC_TAMPERPRECHARGEDURATION_8RTCCLK)) + +#define IS_RTC_TAMPER_PULLUP_STATE(STATE) (((STATE) == RTC_TAMPER_PULLUP_ENABLE) || \ + ((STATE) == RTC_TAMPER_PULLUP_DISABLE)) + +#define IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(DETECTION) (((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_ENABLE) || \ + ((DETECTION) == RTC_TIMESTAMPONTAMPERDETECTION_DISABLE)) + +#define IS_RTC_WAKEUP_CLOCK(CLOCK) (((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV16) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV8) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV4) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_RTCCLK_DIV2) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_16BITS) || \ + ((CLOCK) == RTC_WAKEUPCLOCK_CK_SPRE_17BITS)) + +#define IS_RTC_WAKEUP_COUNTER(COUNTER) ((COUNTER) <= RTC_WUTR_WUT) + +#define IS_RTC_CALIB_SIGN(SIGN) (((SIGN) == RTC_CALIBSIGN_POSITIVE) || \ + ((SIGN) == RTC_CALIBSIGN_NEGATIVE)) + +#define IS_RTC_CALIB_VALUE(VALUE) ((VALUE) < 0x20U) + +#define IS_RTC_SMOOTH_CALIB_PERIOD(PERIOD) (((PERIOD) == RTC_SMOOTHCALIB_PERIOD_32SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_16SEC) || \ + ((PERIOD) == RTC_SMOOTHCALIB_PERIOD_8SEC)) + +#define IS_RTC_SMOOTH_CALIB_PLUS(PLUS) (((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_SET) || \ + ((PLUS) == RTC_SMOOTHCALIB_PLUSPULSES_RESET)) + +#define IS_RTC_SMOOTH_CALIB_MINUS(VALUE) ((VALUE) <= RTC_CALR_CALM) + +#define IS_RTC_SHIFT_ADD1S(SEL) (((SEL) == RTC_SHIFTADD1S_RESET) || \ + ((SEL) == RTC_SHIFTADD1S_SET)) + +#define IS_RTC_SHIFT_SUBFS(FS) ((FS) <= RTC_SHIFTR_SUBFS) + +#define IS_RTC_CALIB_OUTPUT(OUTPUT) (((OUTPUT) == RTC_CALIBOUTPUT_512HZ) || \ + ((OUTPUT) == RTC_CALIBOUTPUT_1HZ)) +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_RTC_EX_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h new file mode 100644 index 0000000..368316d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai.h @@ -0,0 +1,895 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sai.h + * @author MCD Application Team + * @brief Header file of SAI HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_SAI_H +#define __STM32F4xx_HAL_SAI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || \ + defined(STM32F423xx) + +/** @addtogroup SAI + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SAI_Exported_Types SAI Exported Types + * @{ + */ + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_SAI_STATE_RESET = 0x00U, /*!< SAI not yet initialized or disabled */ + HAL_SAI_STATE_READY = 0x01U, /*!< SAI initialized and ready for use */ + HAL_SAI_STATE_BUSY = 0x02U, /*!< SAI internal process is ongoing */ + HAL_SAI_STATE_BUSY_TX = 0x12U, /*!< Data transmission process is ongoing */ + HAL_SAI_STATE_BUSY_RX = 0x22U, /*!< Data reception process is ongoing */ + HAL_SAI_STATE_TIMEOUT = 0x03U, /*!< SAI timeout state */ + HAL_SAI_STATE_ERROR = 0x04U /*!< SAI error state */ +} HAL_SAI_StateTypeDef; + +/** + * @brief SAI Callback prototype + */ +typedef void (*SAIcallback)(void); + +/** @defgroup SAI_Init_Structure_definition SAI Init Structure definition + * @brief SAI Init Structure definition + * @{ + */ +typedef struct +{ + uint32_t AudioMode; /*!< Specifies the SAI Block audio Mode. + This parameter can be a value of @ref SAI_Block_Mode */ + + uint32_t Synchro; /*!< Specifies SAI Block synchronization + This parameter can be a value of @ref SAI_Block_Synchronization */ + + uint32_t SynchroExt; /*!< Specifies SAI external output synchronization, this setup is common + for BlockA and BlockB + This parameter can be a value of @ref SAI_Block_SyncExt + @note: If both audio blocks of same SAI are used, this parameter has + to be set to the same value for each audio block */ + + uint32_t OutputDrive; /*!< Specifies when SAI Block outputs are driven. + This parameter can be a value of @ref SAI_Block_Output_Drive + @note this value has to be set before enabling the audio block + but after the audio block configuration. */ + + uint32_t NoDivider; /*!< Specifies whether master clock will be divided or not. + This parameter can be a value of @ref SAI_Block_NoDivider + @note If bit NODIV in the SAI_xCR1 register is cleared, the frame length + should be aligned to a number equal to a power of 2, from 8 to 256. + If bit NODIV in the SAI_xCR1 register is set, the frame length can + take any of the values without constraint since the input clock of + the audio block should be equal to the bit clock. + There is no MCLK_x clock which can be output. */ + + uint32_t FIFOThreshold; /*!< Specifies SAI Block FIFO threshold. + This parameter can be a value of @ref SAI_Block_Fifo_Threshold */ + + uint32_t ClockSource; /*!< Specifies the SAI Block x Clock source. + This parameter is not used for STM32F446xx devices. */ + + uint32_t AudioFrequency; /*!< Specifies the audio frequency sampling. + This parameter can be a value of @ref SAI_Audio_Frequency */ + + uint32_t Mckdiv; /*!< Specifies the master clock divider. + This parameter must be a number between Min_Data = 0 and Max_Data = 15. + @note This parameter is used only if AudioFrequency is set to + SAI_AUDIO_FREQUENCY_MCKDIV otherwise it is internally computed. */ + + uint32_t MonoStereoMode; /*!< Specifies if the mono or stereo mode is selected. + This parameter can be a value of @ref SAI_Mono_Stereo_Mode */ + + uint32_t CompandingMode; /*!< Specifies the companding mode type. + This parameter can be a value of @ref SAI_Block_Companding_Mode */ + + uint32_t TriState; /*!< Specifies the companding mode type. + This parameter can be a value of @ref SAI_TRIState_Management */ + + /* This part of the structure is automatically filled if your are using the high level initialisation + function HAL_SAI_InitProtocol */ + + uint32_t Protocol; /*!< Specifies the SAI Block protocol. + This parameter can be a value of @ref SAI_Block_Protocol */ + + uint32_t DataSize; /*!< Specifies the SAI Block data size. + This parameter can be a value of @ref SAI_Block_Data_Size */ + + uint32_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SAI_Block_MSB_LSB_transmission */ + + uint32_t ClockStrobing; /*!< Specifies the SAI Block clock strobing edge sensitivity. + This parameter can be a value of @ref SAI_Block_Clock_Strobing */ +} SAI_InitTypeDef; +/** + * @} + */ + +/** @defgroup SAI_Frame_Structure_definition SAI Frame Structure definition + * @brief SAI Frame Init structure definition + * @note For SPDIF and AC97 protocol, these parameters are not used (set by hardware). + * @{ + */ +typedef struct +{ + uint32_t FrameLength; /*!< Specifies the Frame length, the number of SCK clocks for each audio frame. + This parameter must be a number between Min_Data = 8 and Max_Data = 256. + @note If master clock MCLK_x pin is declared as an output, the frame length + should be aligned to a number equal to power of 2 in order to keep + in an audio frame, an integer number of MCLK pulses by bit Clock. */ + + uint32_t ActiveFrameLength; /*!< Specifies the Frame synchronization active level length. + This Parameter specifies the length in number of bit clock (SCK + 1) + of the active level of FS signal in audio frame. + This parameter must be a number between Min_Data = 1 and Max_Data = 128 */ + + uint32_t FSDefinition; /*!< Specifies the Frame synchronization definition. + This parameter can be a value of @ref SAI_Block_FS_Definition */ + + uint32_t FSPolarity; /*!< Specifies the Frame synchronization Polarity. + This parameter can be a value of @ref SAI_Block_FS_Polarity */ + + uint32_t FSOffset; /*!< Specifies the Frame synchronization Offset. + This parameter can be a value of @ref SAI_Block_FS_Offset */ +} SAI_FrameInitTypeDef; +/** + * @} + */ + +/** @defgroup SAI_Slot_Structure_definition SAI Slot Structure definition + * @brief SAI Block Slot Init Structure definition + * @note For SPDIF protocol, these parameters are not used (set by hardware). + * @note For AC97 protocol, only SlotActive parameter is used (the others are set by hardware). + * @{ + */ +typedef struct +{ + uint32_t FirstBitOffset; /*!< Specifies the position of first data transfer bit in the slot. + This parameter must be a number between Min_Data = 0 and Max_Data = 24 */ + + uint32_t SlotSize; /*!< Specifies the Slot Size. + This parameter can be a value of @ref SAI_Block_Slot_Size */ + + uint32_t SlotNumber; /*!< Specifies the number of slot in the audio frame. + This parameter must be a number between Min_Data = 1 and Max_Data = 16 */ + + uint32_t SlotActive; /*!< Specifies the slots in audio frame that will be activated. + This parameter can be a value of @ref SAI_Block_Slot_Active */ +} SAI_SlotInitTypeDef; +/** + * @} + */ + +/** @defgroup SAI_Handle_Structure_definition SAI Handle Structure definition + * @brief SAI handle Structure definition + * @{ + */ +typedef struct __SAI_HandleTypeDef +{ + SAI_Block_TypeDef *Instance; /*!< SAI Blockx registers base address */ + + SAI_InitTypeDef Init; /*!< SAI communication parameters */ + + SAI_FrameInitTypeDef FrameInit; /*!< SAI Frame configuration parameters */ + + SAI_SlotInitTypeDef SlotInit; /*!< SAI Slot configuration parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to SAI transfer Buffer */ + + uint16_t XferSize; /*!< SAI transfer size */ + + uint16_t XferCount; /*!< SAI transfer counter */ + + DMA_HandleTypeDef *hdmatx; /*!< SAI Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< SAI Rx DMA handle parameters */ + + SAIcallback mutecallback;/*!< SAI mute callback */ + + void (*InterruptServiceRoutine)(struct __SAI_HandleTypeDef *hsai); /* function pointer for IRQ handler */ + + HAL_LockTypeDef Lock; /*!< SAI locking object */ + + __IO HAL_SAI_StateTypeDef State; /*!< SAI communication state */ + + __IO uint32_t ErrorCode; /*!< SAI Error code */ + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + void (*RxCpltCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI receive complete callback */ + void (*RxHalfCpltCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI receive half complete callback */ + void (*TxCpltCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI transmit complete callback */ + void (*TxHalfCpltCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI transmit half complete callback */ + void (*ErrorCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI error callback */ + void (*MspInitCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI MSP init callback */ + void (*MspDeInitCallback)(struct __SAI_HandleTypeDef *hsai); /*!< SAI MSP de-init callback */ +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} SAI_HandleTypeDef; +/** + * @} + */ + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) +/** + * @brief SAI callback ID enumeration definition + */ +typedef enum +{ + HAL_SAI_RX_COMPLETE_CB_ID = 0x00U, /*!< SAI receive complete callback ID */ + HAL_SAI_RX_HALFCOMPLETE_CB_ID = 0x01U, /*!< SAI receive half complete callback ID */ + HAL_SAI_TX_COMPLETE_CB_ID = 0x02U, /*!< SAI transmit complete callback ID */ + HAL_SAI_TX_HALFCOMPLETE_CB_ID = 0x03U, /*!< SAI transmit half complete callback ID */ + HAL_SAI_ERROR_CB_ID = 0x04U, /*!< SAI error callback ID */ + HAL_SAI_MSPINIT_CB_ID = 0x05U, /*!< SAI MSP init callback ID */ + HAL_SAI_MSPDEINIT_CB_ID = 0x06U /*!< SAI MSP de-init callback ID */ +} HAL_SAI_CallbackIDTypeDef; + +/** + * @brief SAI callback pointer definition + */ +typedef void (*pSAI_CallbackTypeDef)(SAI_HandleTypeDef *hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SAI_Exported_Constants SAI Exported Constants + * @{ + */ + +/** @defgroup SAI_Error_Code SAI Error Code + * @{ + */ +#define HAL_SAI_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_SAI_ERROR_OVR 0x00000001U /*!< Overrun Error */ +#define HAL_SAI_ERROR_UDR 0x00000002U /*!< Underrun error */ +#define HAL_SAI_ERROR_AFSDET 0x00000004U /*!< Anticipated Frame synchronisation detection */ +#define HAL_SAI_ERROR_LFSDET 0x00000008U /*!< Late Frame synchronisation detection */ +#define HAL_SAI_ERROR_CNREADY 0x00000010U /*!< codec not ready */ +#define HAL_SAI_ERROR_WCKCFG 0x00000020U /*!< Wrong clock configuration */ +#define HAL_SAI_ERROR_TIMEOUT 0x00000040U /*!< Timeout error */ +#define HAL_SAI_ERROR_DMA 0x00000080U /*!< DMA error */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) +#define HAL_SAI_ERROR_INVALID_CALLBACK 0x00000100U /*!< Invalid callback error */ +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SAI_Block_SyncExt SAI External synchronisation + * @{ + */ +#define SAI_SYNCEXT_DISABLE 0U +#define SAI_SYNCEXT_OUTBLOCKA_ENABLE 1U +#define SAI_SYNCEXT_OUTBLOCKB_ENABLE 2U +/** + * @} + */ + +/** @defgroup SAI_Protocol SAI Supported protocol + * @{ + */ +#define SAI_I2S_STANDARD 0U +#define SAI_I2S_MSBJUSTIFIED 1U +#define SAI_I2S_LSBJUSTIFIED 2U +#define SAI_PCM_LONG 3U +#define SAI_PCM_SHORT 4U +/** + * @} + */ + +/** @defgroup SAI_Protocol_DataSize SAI protocol data size + * @{ + */ +#define SAI_PROTOCOL_DATASIZE_16BIT 0U +#define SAI_PROTOCOL_DATASIZE_16BITEXTENDED 1U +#define SAI_PROTOCOL_DATASIZE_24BIT 2U +#define SAI_PROTOCOL_DATASIZE_32BIT 3U +/** + * @} + */ + +/** @defgroup SAI_Audio_Frequency SAI Audio Frequency + * @{ + */ +#define SAI_AUDIO_FREQUENCY_192K 192000U +#define SAI_AUDIO_FREQUENCY_96K 96000U +#define SAI_AUDIO_FREQUENCY_48K 48000U +#define SAI_AUDIO_FREQUENCY_44K 44100U +#define SAI_AUDIO_FREQUENCY_32K 32000U +#define SAI_AUDIO_FREQUENCY_22K 22050U +#define SAI_AUDIO_FREQUENCY_16K 16000U +#define SAI_AUDIO_FREQUENCY_11K 11025U +#define SAI_AUDIO_FREQUENCY_8K 8000U +#define SAI_AUDIO_FREQUENCY_MCKDIV 0U +/** + * @} + */ + +/** @defgroup SAI_Block_Mode SAI Block Mode + * @{ + */ +#define SAI_MODEMASTER_TX 0x00000000U +#define SAI_MODEMASTER_RX ((uint32_t)SAI_xCR1_MODE_0) +#define SAI_MODESLAVE_TX ((uint32_t)SAI_xCR1_MODE_1) +#define SAI_MODESLAVE_RX ((uint32_t)(SAI_xCR1_MODE_1 | SAI_xCR1_MODE_0)) +/** + * @} + */ + +/** @defgroup SAI_Block_Protocol SAI Block Protocol + * @{ + */ +#define SAI_FREE_PROTOCOL 0x00000000U +#define SAI_SPDIF_PROTOCOL ((uint32_t)SAI_xCR1_PRTCFG_0) +#define SAI_AC97_PROTOCOL ((uint32_t)SAI_xCR1_PRTCFG_1) +/** + * @} + */ + +/** @defgroup SAI_Block_Data_Size SAI Block Data Size + * @{ + */ +#define SAI_DATASIZE_8 ((uint32_t)SAI_xCR1_DS_1) +#define SAI_DATASIZE_10 ((uint32_t)(SAI_xCR1_DS_1 | SAI_xCR1_DS_0)) +#define SAI_DATASIZE_16 ((uint32_t)SAI_xCR1_DS_2) +#define SAI_DATASIZE_20 ((uint32_t)(SAI_xCR1_DS_2 | SAI_xCR1_DS_0)) +#define SAI_DATASIZE_24 ((uint32_t)(SAI_xCR1_DS_2 | SAI_xCR1_DS_1)) +#define SAI_DATASIZE_32 ((uint32_t)(SAI_xCR1_DS_2 | SAI_xCR1_DS_1 | SAI_xCR1_DS_0)) +/** + * @} + */ + +/** @defgroup SAI_Block_MSB_LSB_transmission SAI Block MSB LSB transmission + * @{ + */ +#define SAI_FIRSTBIT_MSB 0x00000000U +#define SAI_FIRSTBIT_LSB ((uint32_t)SAI_xCR1_LSBFIRST) +/** + * @} + */ + +/** @defgroup SAI_Block_Clock_Strobing SAI Block Clock Strobing + * @{ + */ +#define SAI_CLOCKSTROBING_FALLINGEDGE 0U +#define SAI_CLOCKSTROBING_RISINGEDGE 1U +/** + * @} + */ + +/** @defgroup SAI_Block_Synchronization SAI Block Synchronization + * @{ + */ +#define SAI_ASYNCHRONOUS 0U /*!< Asynchronous */ +#define SAI_SYNCHRONOUS 1U /*!< Synchronous with other block of same SAI */ +#define SAI_SYNCHRONOUS_EXT_SAI1 2U /*!< Synchronous with other SAI, SAI1 */ +#define SAI_SYNCHRONOUS_EXT_SAI2 3U /*!< Synchronous with other SAI, SAI2 */ +/** + * @} + */ + +/** @defgroup SAI_Block_Output_Drive SAI Block Output Drive + * @{ + */ +#define SAI_OUTPUTDRIVE_DISABLE 0x00000000U +#define SAI_OUTPUTDRIVE_ENABLE ((uint32_t)SAI_xCR1_OUTDRIV) +/** + * @} + */ + +/** @defgroup SAI_Block_NoDivider SAI Block NoDivider + * @{ + */ +#define SAI_MASTERDIVIDER_ENABLE 0x00000000U +#define SAI_MASTERDIVIDER_DISABLE ((uint32_t)SAI_xCR1_NODIV) +/** + * @} + */ + +/** @defgroup SAI_Block_FS_Definition SAI Block FS Definition + * @{ + */ +#define SAI_FS_STARTFRAME 0x00000000U +#define SAI_FS_CHANNEL_IDENTIFICATION ((uint32_t)SAI_xFRCR_FSDEF) +/** + * @} + */ + +/** @defgroup SAI_Block_FS_Polarity SAI Block FS Polarity + * @{ + */ +#define SAI_FS_ACTIVE_LOW 0x00000000U +#define SAI_FS_ACTIVE_HIGH ((uint32_t)SAI_xFRCR_FSPOL) +/** + * @} + */ + +/** @defgroup SAI_Block_FS_Offset SAI Block FS Offset + * @{ + */ +#define SAI_FS_FIRSTBIT 0x00000000U +#define SAI_FS_BEFOREFIRSTBIT ((uint32_t)SAI_xFRCR_FSOFF) +/** + * @} + */ + +/** @defgroup SAI_Block_Slot_Size SAI Block Slot Size + * @{ + */ +#define SAI_SLOTSIZE_DATASIZE 0x00000000U +#define SAI_SLOTSIZE_16B ((uint32_t)SAI_xSLOTR_SLOTSZ_0) +#define SAI_SLOTSIZE_32B ((uint32_t)SAI_xSLOTR_SLOTSZ_1) +/** + * @} + */ + +/** @defgroup SAI_Block_Slot_Active SAI Block Slot Active + * @{ + */ +#define SAI_SLOT_NOTACTIVE 0x00000000U +#define SAI_SLOTACTIVE_0 0x00000001U +#define SAI_SLOTACTIVE_1 0x00000002U +#define SAI_SLOTACTIVE_2 0x00000004U +#define SAI_SLOTACTIVE_3 0x00000008U +#define SAI_SLOTACTIVE_4 0x00000010U +#define SAI_SLOTACTIVE_5 0x00000020U +#define SAI_SLOTACTIVE_6 0x00000040U +#define SAI_SLOTACTIVE_7 0x00000080U +#define SAI_SLOTACTIVE_8 0x00000100U +#define SAI_SLOTACTIVE_9 0x00000200U +#define SAI_SLOTACTIVE_10 0x00000400U +#define SAI_SLOTACTIVE_11 0x00000800U +#define SAI_SLOTACTIVE_12 0x00001000U +#define SAI_SLOTACTIVE_13 0x00002000U +#define SAI_SLOTACTIVE_14 0x00004000U +#define SAI_SLOTACTIVE_15 0x00008000U +#define SAI_SLOTACTIVE_ALL 0x0000FFFFU +/** + * @} + */ + +/** @defgroup SAI_Mono_Stereo_Mode SAI Mono Stereo Mode + * @{ + */ +#define SAI_STEREOMODE 0x00000000U +#define SAI_MONOMODE ((uint32_t)SAI_xCR1_MONO) +/** + * @} + */ + +/** @defgroup SAI_TRIState_Management SAI TRIState Management + * @{ + */ +#define SAI_OUTPUT_NOTRELEASED 0x00000000U +#define SAI_OUTPUT_RELEASED ((uint32_t)SAI_xCR2_TRIS) +/** + * @} + */ + +/** @defgroup SAI_Block_Fifo_Threshold SAI Block Fifo Threshold + * @{ + */ +#define SAI_FIFOTHRESHOLD_EMPTY 0x00000000U +#define SAI_FIFOTHRESHOLD_1QF ((uint32_t)(SAI_xCR2_FTH_0)) +#define SAI_FIFOTHRESHOLD_HF ((uint32_t)(SAI_xCR2_FTH_1)) +#define SAI_FIFOTHRESHOLD_3QF ((uint32_t)(SAI_xCR2_FTH_1 | SAI_xCR2_FTH_0)) +#define SAI_FIFOTHRESHOLD_FULL ((uint32_t)(SAI_xCR2_FTH_2)) +/** + * @} + */ + +/** @defgroup SAI_Block_Companding_Mode SAI Block Companding Mode + * @{ + */ +#define SAI_NOCOMPANDING 0x00000000U +#define SAI_ULAW_1CPL_COMPANDING ((uint32_t)(SAI_xCR2_COMP_1)) +#define SAI_ALAW_1CPL_COMPANDING ((uint32_t)(SAI_xCR2_COMP_1 | SAI_xCR2_COMP_0)) +#define SAI_ULAW_2CPL_COMPANDING ((uint32_t)(SAI_xCR2_COMP_1 | SAI_xCR2_CPL)) +#define SAI_ALAW_2CPL_COMPANDING ((uint32_t)(SAI_xCR2_COMP_1 | SAI_xCR2_COMP_0 | SAI_xCR2_CPL)) +/** + * @} + */ + +/** @defgroup SAI_Block_Mute_Value SAI Block Mute Value + * @{ + */ +#define SAI_ZERO_VALUE 0x00000000U +#define SAI_LAST_SENT_VALUE ((uint32_t)SAI_xCR2_MUTEVAL) +/** + * @} + */ + +/** @defgroup SAI_Block_Interrupts_Definition SAI Block Interrupts Definition + * @{ + */ +#define SAI_IT_OVRUDR ((uint32_t)SAI_xIMR_OVRUDRIE) +#define SAI_IT_MUTEDET ((uint32_t)SAI_xIMR_MUTEDETIE) +#define SAI_IT_WCKCFG ((uint32_t)SAI_xIMR_WCKCFGIE) +#define SAI_IT_FREQ ((uint32_t)SAI_xIMR_FREQIE) +#define SAI_IT_CNRDY ((uint32_t)SAI_xIMR_CNRDYIE) +#define SAI_IT_AFSDET ((uint32_t)SAI_xIMR_AFSDETIE) +#define SAI_IT_LFSDET ((uint32_t)SAI_xIMR_LFSDETIE) +/** + * @} + */ + +/** @defgroup SAI_Block_Flags_Definition SAI Block Flags Definition + * @{ + */ +#define SAI_FLAG_OVRUDR ((uint32_t)SAI_xSR_OVRUDR) +#define SAI_FLAG_MUTEDET ((uint32_t)SAI_xSR_MUTEDET) +#define SAI_FLAG_WCKCFG ((uint32_t)SAI_xSR_WCKCFG) +#define SAI_FLAG_FREQ ((uint32_t)SAI_xSR_FREQ) +#define SAI_FLAG_CNRDY ((uint32_t)SAI_xSR_CNRDY) +#define SAI_FLAG_AFSDET ((uint32_t)SAI_xSR_AFSDET) +#define SAI_FLAG_LFSDET ((uint32_t)SAI_xSR_LFSDET) +/** + * @} + */ + +/** @defgroup SAI_Block_Fifo_Status_Level SAI Block Fifo Status Level + * @{ + */ +#define SAI_FIFOSTATUS_EMPTY 0x00000000U +#define SAI_FIFOSTATUS_LESS1QUARTERFULL 0x00010000U +#define SAI_FIFOSTATUS_1QUARTERFULL 0x00020000U +#define SAI_FIFOSTATUS_HALFFULL 0x00030000U +#define SAI_FIFOSTATUS_3QUARTERFULL 0x00040000U +#define SAI_FIFOSTATUS_FULL 0x00050000U +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SAI_Exported_Macros SAI Exported Macros + * @brief macros to handle interrupts and specific configurations + * @{ + */ + +/** @brief Reset SAI handle state + * @param __HANDLE__ specifies the SAI Handle. + * @retval None + */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) +#define __HAL_SAI_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_SAI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_SAI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SAI_STATE_RESET) +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + +/** @brief Enable or disable the specified SAI interrupts. + * @param __HANDLE__ specifies the SAI Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg SAI_IT_OVRUDR: Overrun underrun interrupt enable + * @arg SAI_IT_MUTEDET: Mute detection interrupt enable + * @arg SAI_IT_WCKCFG: Wrong Clock Configuration interrupt enable + * @arg SAI_IT_FREQ: FIFO request interrupt enable + * @arg SAI_IT_CNRDY: Codec not ready interrupt enable + * @arg SAI_IT_AFSDET: Anticipated frame synchronization detection interrupt enable + * @arg SAI_IT_LFSDET: Late frame synchronization detection interrupt enable + * @retval None + */ +#define __HAL_SAI_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IMR |= (__INTERRUPT__)) +#define __HAL_SAI_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IMR &= (~(__INTERRUPT__))) + +/** @brief Check if the specified SAI interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the SAI Handle. + * This parameter can be SAI where x: 1, 2, or 3 to select the SAI peripheral. + * @param __INTERRUPT__ specifies the SAI interrupt source to check. + * This parameter can be one of the following values: + * @arg SAI_IT_OVRUDR: Overrun underrun interrupt enable + * @arg SAI_IT_MUTEDET: Mute detection interrupt enable + * @arg SAI_IT_WCKCFG: Wrong Clock Configuration interrupt enable + * @arg SAI_IT_FREQ: FIFO request interrupt enable + * @arg SAI_IT_CNRDY: Codec not ready interrupt enable + * @arg SAI_IT_AFSDET: Anticipated frame synchronization detection interrupt enable + * @arg SAI_IT_LFSDET: Late frame synchronization detection interrupt enable + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_SAI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->IMR & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified SAI flag is set or not. + * @param __HANDLE__ specifies the SAI Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SAI_FLAG_OVRUDR: Overrun underrun flag. + * @arg SAI_FLAG_MUTEDET: Mute detection flag. + * @arg SAI_FLAG_WCKCFG: Wrong Clock Configuration flag. + * @arg SAI_FLAG_FREQ: FIFO request flag. + * @arg SAI_FLAG_CNRDY: Codec not ready flag. + * @arg SAI_FLAG_AFSDET: Anticipated frame synchronization detection flag. + * @arg SAI_FLAG_LFSDET: Late frame synchronization detection flag. + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SAI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified SAI pending flag. + * @param __HANDLE__ specifies the SAI Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg SAI_FLAG_OVRUDR: Clear Overrun underrun + * @arg SAI_FLAG_MUTEDET: Clear Mute detection + * @arg SAI_FLAG_WCKCFG: Clear Wrong Clock Configuration + * @arg SAI_FLAG_FREQ: Clear FIFO request + * @arg SAI_FLAG_CNRDY: Clear Codec not ready + * @arg SAI_FLAG_AFSDET: Clear Anticipated frame synchronization detection + * @arg SAI_FLAG_LFSDET: Clear Late frame synchronization detection + * @retval None + */ +#define __HAL_SAI_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->CLRFR = (__FLAG__)) + +/** @brief Enable SAI + * @param __HANDLE__ specifies the SAI Handle. + * @retval None + */ +#define __HAL_SAI_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= SAI_xCR1_SAIEN) + +/** @brief Disable SAI + * @param __HANDLE__ specifies the SAI Handle. + * @retval None + */ +#define __HAL_SAI_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~SAI_xCR1_SAIEN) + +/** + * @} + */ + +/* Include HAL SAI Extension module */ +#include "stm32f4xx_hal_sai_ex.h" + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SAI_Exported_Functions + * @{ + */ + +/* Initialization/de-initialization functions **********************************/ +/** @addtogroup SAI_Exported_Functions_Group1 + * @{ + */ +HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); +HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai); +HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai); +void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai); +void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai); + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) +/* SAI callbacks register/unregister functions ********************************/ +HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai, + HAL_SAI_CallbackIDTypeDef CallbackID, + pSAI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai, + HAL_SAI_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* I/O operation functions *****************************************************/ +/** @addtogroup SAI_Exported_Functions_Group2 + * @{ + */ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size); + +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai); +HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai); +HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai); + +/* Abort function */ +HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai); + +/* Mute management */ +HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val); +HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai); +HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter); +HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai); + +/* SAI IRQHandler and Callbacks used in non blocking modes (Interrupt and DMA) */ +void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai); +void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai); +void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai); +void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai); +void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai); +void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai); +/** + * @} + */ + +/** @addtogroup SAI_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai); +uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai); +/** + * @} + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup SAI_Private_Macros + * @{ + */ +#define IS_SAI_BLOCK_SYNCEXT(STATE) (((STATE) == SAI_SYNCEXT_DISABLE) ||\ + ((STATE) == SAI_SYNCEXT_OUTBLOCKA_ENABLE) ||\ + ((STATE) == SAI_SYNCEXT_OUTBLOCKB_ENABLE)) + +#define IS_SAI_SUPPORTED_PROTOCOL(PROTOCOL) (((PROTOCOL) == SAI_I2S_STANDARD) ||\ + ((PROTOCOL) == SAI_I2S_MSBJUSTIFIED) ||\ + ((PROTOCOL) == SAI_I2S_LSBJUSTIFIED) ||\ + ((PROTOCOL) == SAI_PCM_LONG) ||\ + ((PROTOCOL) == SAI_PCM_SHORT)) + +#define IS_SAI_PROTOCOL_DATASIZE(DATASIZE) (((DATASIZE) == SAI_PROTOCOL_DATASIZE_16BIT) ||\ + ((DATASIZE) == SAI_PROTOCOL_DATASIZE_16BITEXTENDED) ||\ + ((DATASIZE) == SAI_PROTOCOL_DATASIZE_24BIT) ||\ + ((DATASIZE) == SAI_PROTOCOL_DATASIZE_32BIT)) + +#define IS_SAI_AUDIO_FREQUENCY(AUDIO) (((AUDIO) == SAI_AUDIO_FREQUENCY_192K) || ((AUDIO) == SAI_AUDIO_FREQUENCY_96K) || \ + ((AUDIO) == SAI_AUDIO_FREQUENCY_48K) || ((AUDIO) == SAI_AUDIO_FREQUENCY_44K) || \ + ((AUDIO) == SAI_AUDIO_FREQUENCY_32K) || ((AUDIO) == SAI_AUDIO_FREQUENCY_22K) || \ + ((AUDIO) == SAI_AUDIO_FREQUENCY_16K) || ((AUDIO) == SAI_AUDIO_FREQUENCY_11K) || \ + ((AUDIO) == SAI_AUDIO_FREQUENCY_8K) || ((AUDIO) == SAI_AUDIO_FREQUENCY_MCKDIV)) + +#define IS_SAI_BLOCK_MODE(MODE) (((MODE) == SAI_MODEMASTER_TX) || \ + ((MODE) == SAI_MODEMASTER_RX) || \ + ((MODE) == SAI_MODESLAVE_TX) || \ + ((MODE) == SAI_MODESLAVE_RX)) + +#define IS_SAI_BLOCK_PROTOCOL(PROTOCOL) (((PROTOCOL) == SAI_FREE_PROTOCOL) || \ + ((PROTOCOL) == SAI_AC97_PROTOCOL) || \ + ((PROTOCOL) == SAI_SPDIF_PROTOCOL)) + +#define IS_SAI_BLOCK_DATASIZE(DATASIZE) (((DATASIZE) == SAI_DATASIZE_8) || \ + ((DATASIZE) == SAI_DATASIZE_10) || \ + ((DATASIZE) == SAI_DATASIZE_16) || \ + ((DATASIZE) == SAI_DATASIZE_20) || \ + ((DATASIZE) == SAI_DATASIZE_24) || \ + ((DATASIZE) == SAI_DATASIZE_32)) + +#define IS_SAI_BLOCK_FIRST_BIT(BIT) (((BIT) == SAI_FIRSTBIT_MSB) || \ + ((BIT) == SAI_FIRSTBIT_LSB)) + +#define IS_SAI_BLOCK_CLOCK_STROBING(CLOCK) (((CLOCK) == SAI_CLOCKSTROBING_FALLINGEDGE) || \ + ((CLOCK) == SAI_CLOCKSTROBING_RISINGEDGE)) + +#define IS_SAI_BLOCK_SYNCHRO(SYNCHRO) (((SYNCHRO) == SAI_ASYNCHRONOUS) || \ + ((SYNCHRO) == SAI_SYNCHRONOUS) || \ + ((SYNCHRO) == SAI_SYNCHRONOUS_EXT_SAI1) ||\ + ((SYNCHRO) == SAI_SYNCHRONOUS_EXT_SAI2)) + +#define IS_SAI_BLOCK_OUTPUT_DRIVE(DRIVE) (((DRIVE) == SAI_OUTPUTDRIVE_DISABLE) || \ + ((DRIVE) == SAI_OUTPUTDRIVE_ENABLE)) + +#define IS_SAI_BLOCK_NODIVIDER(NODIVIDER) (((NODIVIDER) == SAI_MASTERDIVIDER_ENABLE) || \ + ((NODIVIDER) == SAI_MASTERDIVIDER_DISABLE)) + +#define IS_SAI_BLOCK_MUTE_COUNTER(COUNTER) ((COUNTER) <= 63U) + +#define IS_SAI_BLOCK_MUTE_VALUE(VALUE) (((VALUE) == SAI_ZERO_VALUE) || \ + ((VALUE) == SAI_LAST_SENT_VALUE)) + +#define IS_SAI_BLOCK_COMPANDING_MODE(MODE) (((MODE) == SAI_NOCOMPANDING) || \ + ((MODE) == SAI_ULAW_1CPL_COMPANDING) || \ + ((MODE) == SAI_ALAW_1CPL_COMPANDING) || \ + ((MODE) == SAI_ULAW_2CPL_COMPANDING) || \ + ((MODE) == SAI_ALAW_2CPL_COMPANDING)) + +#define IS_SAI_BLOCK_FIFO_THRESHOLD(THRESHOLD) (((THRESHOLD) == SAI_FIFOTHRESHOLD_EMPTY) || \ + ((THRESHOLD) == SAI_FIFOTHRESHOLD_1QF) || \ + ((THRESHOLD) == SAI_FIFOTHRESHOLD_HF) || \ + ((THRESHOLD) == SAI_FIFOTHRESHOLD_3QF) || \ + ((THRESHOLD) == SAI_FIFOTHRESHOLD_FULL)) + +#define IS_SAI_BLOCK_TRISTATE_MANAGEMENT(STATE) (((STATE) == SAI_OUTPUT_NOTRELEASED) ||\ + ((STATE) == SAI_OUTPUT_RELEASED)) + +#define IS_SAI_MONO_STEREO_MODE(MODE) (((MODE) == SAI_MONOMODE) ||\ + ((MODE) == SAI_STEREOMODE)) + +#define IS_SAI_SLOT_ACTIVE(ACTIVE) ((ACTIVE) <= SAI_SLOTACTIVE_ALL) + +#define IS_SAI_BLOCK_SLOT_NUMBER(NUMBER) ((1U <= (NUMBER)) && ((NUMBER) <= 16U)) + +#define IS_SAI_BLOCK_SLOT_SIZE(SIZE) (((SIZE) == SAI_SLOTSIZE_DATASIZE) || \ + ((SIZE) == SAI_SLOTSIZE_16B) || \ + ((SIZE) == SAI_SLOTSIZE_32B)) + +#define IS_SAI_BLOCK_FIRSTBIT_OFFSET(OFFSET) ((OFFSET) <= 24U) + +#define IS_SAI_BLOCK_FS_OFFSET(OFFSET) (((OFFSET) == SAI_FS_FIRSTBIT) || \ + ((OFFSET) == SAI_FS_BEFOREFIRSTBIT)) + +#define IS_SAI_BLOCK_FS_POLARITY(POLARITY) (((POLARITY) == SAI_FS_ACTIVE_LOW) || \ + ((POLARITY) == SAI_FS_ACTIVE_HIGH)) + +#define IS_SAI_BLOCK_FS_DEFINITION(DEFINITION) (((DEFINITION) == SAI_FS_STARTFRAME) || \ + ((DEFINITION) == SAI_FS_CHANNEL_IDENTIFICATION)) + +#define IS_SAI_BLOCK_MASTER_DIVIDER(DIVIDER) ((DIVIDER) <= 15U) + +#define IS_SAI_BLOCK_FRAME_LENGTH(LENGTH) ((8U <= (LENGTH)) && ((LENGTH) <= 256U)) + +#define IS_SAI_BLOCK_ACTIVE_FRAME(LENGTH) ((1U <= (LENGTH)) && ((LENGTH) <= 128U)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SAI_Private_Functions SAI Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_SAI_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h new file mode 100644 index 0000000..75ba6d2 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sai_ex.h @@ -0,0 +1,114 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sai_ex.h + * @author MCD Application Team + * @brief Header file of SAI Extension HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_HAL_SAI_EX_H +#define __STM32F4xx_HAL_SAI_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SAIEx + * @{ + */ + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || \ + defined(STM32F423xx) + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SAI_Clock_Source SAI Clock Source + * @{ + */ +#if defined(STM32F413xx) || defined(STM32F423xx) +#define SAI_CLKSOURCE_PLLI2S 0x00000000U +#define SAI_CLKSOURCE_EXT 0x00100000U +#define SAI_CLKSOURCE_PLLR 0x00200000U +#define SAI_CLKSOURCE_HS 0x00300000U +#else +#define SAI_CLKSOURCE_PLLSAI 0x00000000U +#define SAI_CLKSOURCE_PLLI2S 0x00100000U +#define SAI_CLKSOURCE_EXT 0x00200000U +#define SAI_CLKSOURCE_NA 0x00400000U /*!< No applicable for STM32F446xx */ +#endif + + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SAIEx_Exported_Functions + * @{ + */ + +/** @addtogroup SAIEx_Exported_Functions_Group1 + * @{ + */ + +/* Extended features functions ************************************************/ +void SAI_BlockSynchroConfig(const SAI_HandleTypeDef *hsai); +uint32_t SAI_GetInputClock(const SAI_HandleTypeDef *hsai); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +#if defined(STM32F413xx) || defined(STM32F423xx) +#define IS_SAI_CLK_SOURCE(SOURCE) (((SOURCE) == SAI_CLKSOURCE_PLLI2S) ||\ + ((SOURCE) == SAI_CLKSOURCE_EXT)||\ + ((SOURCE) == SAI_CLKSOURCE_PLLR)||\ + ((SOURCE) == SAI_CLKSOURCE_HS)) +#else +#define IS_SAI_CLK_SOURCE(SOURCE) (((SOURCE) == SAI_CLKSOURCE_PLLSAI) ||\ + ((SOURCE) == SAI_CLKSOURCE_EXT)||\ + ((SOURCE) == SAI_CLKSOURCE_PLLI2S)||\ + ((SOURCE) == SAI_CLKSOURCE_NA)) +#endif +/* Private functions ---------------------------------------------------------*/ + +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_SAI_EX_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h new file mode 100644 index 0000000..73fc7de --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sd.h @@ -0,0 +1,758 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sd.h + * @author MCD Application Team + * @brief Header file of SD 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 STM32F4xx_HAL_SD_H +#define STM32F4xx_HAL_SD_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(SDIO) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_sdmmc.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SD SD + * @brief SD HAL module driver + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SD_Exported_Types SD Exported Types + * @{ + */ + +/** @defgroup SD_Exported_Types_Group1 SD State enumeration structure + * @{ + */ +typedef enum +{ + HAL_SD_STATE_RESET = 0x00000000U, /*!< SD not yet initialized or disabled */ + HAL_SD_STATE_READY = 0x00000001U, /*!< SD initialized and ready for use */ + HAL_SD_STATE_TIMEOUT = 0x00000002U, /*!< SD Timeout state */ + HAL_SD_STATE_BUSY = 0x00000003U, /*!< SD process ongoing */ + HAL_SD_STATE_PROGRAMMING = 0x00000004U, /*!< SD Programming State */ + HAL_SD_STATE_RECEIVING = 0x00000005U, /*!< SD Receiving State */ + HAL_SD_STATE_TRANSFER = 0x00000006U, /*!< SD Transfer State */ + HAL_SD_STATE_ERROR = 0x0000000FU /*!< SD is in error state */ +}HAL_SD_StateTypeDef; +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group2 SD Card State enumeration structure + * @{ + */ +typedef uint32_t HAL_SD_CardStateTypeDef; + +#define HAL_SD_CARD_READY 0x00000001U /*!< Card state is ready */ +#define HAL_SD_CARD_IDENTIFICATION 0x00000002U /*!< Card is in identification state */ +#define HAL_SD_CARD_STANDBY 0x00000003U /*!< Card is in standby state */ +#define HAL_SD_CARD_TRANSFER 0x00000004U /*!< Card is in transfer state */ +#define HAL_SD_CARD_SENDING 0x00000005U /*!< Card is sending an operation */ +#define HAL_SD_CARD_RECEIVING 0x00000006U /*!< Card is receiving operation information */ +#define HAL_SD_CARD_PROGRAMMING 0x00000007U /*!< Card is in programming state */ +#define HAL_SD_CARD_DISCONNECTED 0x00000008U /*!< Card is disconnected */ +#define HAL_SD_CARD_ERROR 0x000000FFU /*!< Card response Error */ +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group3 SD Handle Structure definition + * @{ + */ +#define SD_InitTypeDef SDIO_InitTypeDef +#define SD_TypeDef SDIO_TypeDef + +/** + * @brief SD Card Information Structure definition + */ +typedef struct +{ + uint32_t CardType; /*!< Specifies the card Type */ + + uint32_t CardVersion; /*!< Specifies the card version */ + + uint32_t Class; /*!< Specifies the class of the card class */ + + uint32_t RelCardAdd; /*!< Specifies the Relative Card Address */ + + uint32_t BlockNbr; /*!< Specifies the Card Capacity in blocks */ + + uint32_t BlockSize; /*!< Specifies one block size in bytes */ + + uint32_t LogBlockNbr; /*!< Specifies the Card logical Capacity in blocks */ + + uint32_t LogBlockSize; /*!< Specifies logical block size in bytes */ + +}HAL_SD_CardInfoTypeDef; + +/** + * @brief SD handle Structure definition + */ +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +typedef struct __SD_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ +{ + SD_TypeDef *Instance; /*!< SD registers base address */ + + SD_InitTypeDef Init; /*!< SD required parameters */ + + HAL_LockTypeDef Lock; /*!< SD locking object */ + + uint8_t *pTxBuffPtr; /*!< Pointer to SD Tx transfer Buffer */ + + uint32_t TxXferSize; /*!< SD Tx Transfer size */ + + uint8_t *pRxBuffPtr; /*!< Pointer to SD Rx transfer Buffer */ + + uint32_t RxXferSize; /*!< SD Rx Transfer size */ + + __IO uint32_t Context; /*!< SD transfer context */ + + __IO HAL_SD_StateTypeDef State; /*!< SD card State */ + + __IO uint32_t ErrorCode; /*!< SD Card Error codes */ + + DMA_HandleTypeDef *hdmatx; /*!< SD Tx DMA handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< SD Rx DMA handle parameters */ + + HAL_SD_CardInfoTypeDef SdCard; /*!< SD Card information */ + + uint32_t CSD[4]; /*!< SD card specific data table */ + + uint32_t CID[4]; /*!< SD card identification number table */ + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + void (* TxCpltCallback) (struct __SD_HandleTypeDef *hsd); + void (* RxCpltCallback) (struct __SD_HandleTypeDef *hsd); + void (* ErrorCallback) (struct __SD_HandleTypeDef *hsd); + void (* AbortCpltCallback) (struct __SD_HandleTypeDef *hsd); + + void (* MspInitCallback) (struct __SD_HandleTypeDef *hsd); + void (* MspDeInitCallback) (struct __SD_HandleTypeDef *hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ +}SD_HandleTypeDef; + +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group4 Card Specific Data: CSD Register + * @{ + */ +typedef struct +{ + __IO uint8_t CSDStruct; /*!< CSD structure */ + __IO uint8_t SysSpecVersion; /*!< System specification version */ + __IO uint8_t Reserved1; /*!< Reserved */ + __IO uint8_t TAAC; /*!< Data read access time 1 */ + __IO uint8_t NSAC; /*!< Data read access time 2 in CLK cycles */ + __IO uint8_t MaxBusClkFrec; /*!< Max. bus clock frequency */ + __IO uint16_t CardComdClasses; /*!< Card command classes */ + __IO uint8_t RdBlockLen; /*!< Max. read data block length */ + __IO uint8_t PartBlockRead; /*!< Partial blocks for read allowed */ + __IO uint8_t WrBlockMisalign; /*!< Write block misalignment */ + __IO uint8_t RdBlockMisalign; /*!< Read block misalignment */ + __IO uint8_t DSRImpl; /*!< DSR implemented */ + __IO uint8_t Reserved2; /*!< Reserved */ + __IO uint32_t DeviceSize; /*!< Device Size */ + __IO uint8_t MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */ + __IO uint8_t MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */ + __IO uint8_t MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */ + __IO uint8_t MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */ + __IO uint8_t DeviceSizeMul; /*!< Device size multiplier */ + __IO uint8_t EraseGrSize; /*!< Erase group size */ + __IO uint8_t EraseGrMul; /*!< Erase group size multiplier */ + __IO uint8_t WrProtectGrSize; /*!< Write protect group size */ + __IO uint8_t WrProtectGrEnable; /*!< Write protect group enable */ + __IO uint8_t ManDeflECC; /*!< Manufacturer default ECC */ + __IO uint8_t WrSpeedFact; /*!< Write speed factor */ + __IO uint8_t MaxWrBlockLen; /*!< Max. write data block length */ + __IO uint8_t WriteBlockPaPartial; /*!< Partial blocks for write allowed */ + __IO uint8_t Reserved3; /*!< Reserved */ + __IO uint8_t ContentProtectAppli; /*!< Content protection application */ + __IO uint8_t FileFormatGroup; /*!< File format group */ + __IO uint8_t CopyFlag; /*!< Copy flag (OTP) */ + __IO uint8_t PermWrProtect; /*!< Permanent write protection */ + __IO uint8_t TempWrProtect; /*!< Temporary write protection */ + __IO uint8_t FileFormat; /*!< File format */ + __IO uint8_t ECC; /*!< ECC code */ + __IO uint8_t CSD_CRC; /*!< CSD CRC */ + __IO uint8_t Reserved4; /*!< Always 1 */ +}HAL_SD_CardCSDTypeDef; +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group5 Card Identification Data: CID Register + * @{ + */ +typedef struct +{ + __IO uint8_t ManufacturerID; /*!< Manufacturer ID */ + __IO uint16_t OEM_AppliID; /*!< OEM/Application ID */ + __IO uint32_t ProdName1; /*!< Product Name part1 */ + __IO uint8_t ProdName2; /*!< Product Name part2 */ + __IO uint8_t ProdRev; /*!< Product Revision */ + __IO uint32_t ProdSN; /*!< Product Serial Number */ + __IO uint8_t Reserved1; /*!< Reserved1 */ + __IO uint16_t ManufactDate; /*!< Manufacturing Date */ + __IO uint8_t CID_CRC; /*!< CID CRC */ + __IO uint8_t Reserved2; /*!< Always 1 */ + +}HAL_SD_CardCIDTypeDef; +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group6 SD Card Status returned by ACMD13 + * @{ + */ +typedef struct +{ + __IO uint8_t DataBusWidth; /*!< Shows the currently defined data bus width */ + __IO uint8_t SecuredMode; /*!< Card is in secured mode of operation */ + __IO uint16_t CardType; /*!< Carries information about card type */ + __IO uint32_t ProtectedAreaSize; /*!< Carries information about the capacity of protected area */ + __IO uint8_t SpeedClass; /*!< Carries information about the speed class of the card */ + __IO uint8_t PerformanceMove; /*!< Carries information about the card's performance move */ + __IO uint8_t AllocationUnitSize; /*!< Carries information about the card's allocation unit size */ + __IO uint16_t EraseSize; /*!< Determines the number of AUs to be erased in one operation */ + __IO uint8_t EraseTimeout; /*!< Determines the timeout for any number of AU erase */ + __IO uint8_t EraseOffset; /*!< Carries information about the erase offset */ + +}HAL_SD_CardStatusTypeDef; +/** + * @} + */ + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +/** @defgroup SD_Exported_Types_Group7 SD Callback ID enumeration definition + * @{ + */ +typedef enum +{ + HAL_SD_TX_CPLT_CB_ID = 0x00U, /*!< SD Tx Complete Callback ID */ + HAL_SD_RX_CPLT_CB_ID = 0x01U, /*!< SD Rx Complete Callback ID */ + HAL_SD_ERROR_CB_ID = 0x02U, /*!< SD Error Callback ID */ + HAL_SD_ABORT_CB_ID = 0x03U, /*!< SD Abort Callback ID */ + + HAL_SD_MSP_INIT_CB_ID = 0x10U, /*!< SD MspInit Callback ID */ + HAL_SD_MSP_DEINIT_CB_ID = 0x11U /*!< SD MspDeInit Callback ID */ +}HAL_SD_CallbackIDTypeDef; +/** + * @} + */ + +/** @defgroup SD_Exported_Types_Group8 SD Callback pointer definition + * @{ + */ +typedef void (*pSD_CallbackTypeDef) (SD_HandleTypeDef *hsd); +/** + * @} + */ +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SD_Exported_Constants Exported Constants + * @{ + */ + +#define BLOCKSIZE 512U /*!< Block size is 512 bytes */ + +/** @defgroup SD_Exported_Constansts_Group1 SD Error status enumeration Structure definition + * @{ + */ +#define HAL_SD_ERROR_NONE SDMMC_ERROR_NONE /*!< No error */ +#define HAL_SD_ERROR_CMD_CRC_FAIL SDMMC_ERROR_CMD_CRC_FAIL /*!< Command response received (but CRC check failed) */ +#define HAL_SD_ERROR_DATA_CRC_FAIL SDMMC_ERROR_DATA_CRC_FAIL /*!< Data block sent/received (CRC check failed) */ +#define HAL_SD_ERROR_CMD_RSP_TIMEOUT SDMMC_ERROR_CMD_RSP_TIMEOUT /*!< Command response timeout */ +#define HAL_SD_ERROR_DATA_TIMEOUT SDMMC_ERROR_DATA_TIMEOUT /*!< Data timeout */ +#define HAL_SD_ERROR_TX_UNDERRUN SDMMC_ERROR_TX_UNDERRUN /*!< Transmit FIFO underrun */ +#define HAL_SD_ERROR_RX_OVERRUN SDMMC_ERROR_RX_OVERRUN /*!< Receive FIFO overrun */ +#define HAL_SD_ERROR_ADDR_MISALIGNED SDMMC_ERROR_ADDR_MISALIGNED /*!< Misaligned address */ +#define HAL_SD_ERROR_BLOCK_LEN_ERR SDMMC_ERROR_BLOCK_LEN_ERR /*!< Transferred block length is not allowed for the card or the + number of transferred bytes does not match the block length */ +#define HAL_SD_ERROR_ERASE_SEQ_ERR SDMMC_ERROR_ERASE_SEQ_ERR /*!< An error in the sequence of erase command occurs */ +#define HAL_SD_ERROR_BAD_ERASE_PARAM SDMMC_ERROR_BAD_ERASE_PARAM /*!< An invalid selection for erase groups */ +#define HAL_SD_ERROR_WRITE_PROT_VIOLATION SDMMC_ERROR_WRITE_PROT_VIOLATION /*!< Attempt to program a write protect block */ +#define HAL_SD_ERROR_LOCK_UNLOCK_FAILED SDMMC_ERROR_LOCK_UNLOCK_FAILED /*!< Sequence or password error has been detected in unlock + command or if there was an attempt to access a locked card */ +#define HAL_SD_ERROR_COM_CRC_FAILED SDMMC_ERROR_COM_CRC_FAILED /*!< CRC check of the previous command failed */ +#define HAL_SD_ERROR_ILLEGAL_CMD SDMMC_ERROR_ILLEGAL_CMD /*!< Command is not legal for the card state */ +#define HAL_SD_ERROR_CARD_ECC_FAILED SDMMC_ERROR_CARD_ECC_FAILED /*!< Card internal ECC was applied but failed to correct the data */ +#define HAL_SD_ERROR_CC_ERR SDMMC_ERROR_CC_ERR /*!< Internal card controller error */ +#define HAL_SD_ERROR_GENERAL_UNKNOWN_ERR SDMMC_ERROR_GENERAL_UNKNOWN_ERR /*!< General or unknown error */ +#define HAL_SD_ERROR_STREAM_READ_UNDERRUN SDMMC_ERROR_STREAM_READ_UNDERRUN /*!< The card could not sustain data reading in stream rmode */ +#define HAL_SD_ERROR_STREAM_WRITE_OVERRUN SDMMC_ERROR_STREAM_WRITE_OVERRUN /*!< The card could not sustain data programming in stream mode */ +#define HAL_SD_ERROR_CID_CSD_OVERWRITE SDMMC_ERROR_CID_CSD_OVERWRITE /*!< CID/CSD overwrite error */ +#define HAL_SD_ERROR_WP_ERASE_SKIP SDMMC_ERROR_WP_ERASE_SKIP /*!< Only partial address space was erased */ +#define HAL_SD_ERROR_CARD_ECC_DISABLED SDMMC_ERROR_CARD_ECC_DISABLED /*!< Command has been executed without using internal ECC */ +#define HAL_SD_ERROR_ERASE_RESET SDMMC_ERROR_ERASE_RESET /*!< Erase sequence was cleared before executing because an out + of erase sequence command was received */ +#define HAL_SD_ERROR_AKE_SEQ_ERR SDMMC_ERROR_AKE_SEQ_ERR /*!< Error in sequence of authentication */ +#define HAL_SD_ERROR_INVALID_VOLTRANGE SDMMC_ERROR_INVALID_VOLTRANGE /*!< Error in case of invalid voltage range */ +#define HAL_SD_ERROR_ADDR_OUT_OF_RANGE SDMMC_ERROR_ADDR_OUT_OF_RANGE /*!< Error when addressed block is out of range */ +#define HAL_SD_ERROR_REQUEST_NOT_APPLICABLE SDMMC_ERROR_REQUEST_NOT_APPLICABLE /*!< Error when command request is not applicable */ +#define HAL_SD_ERROR_PARAM SDMMC_ERROR_INVALID_PARAMETER /*!< the used parameter is not valid */ +#define HAL_SD_ERROR_UNSUPPORTED_FEATURE SDMMC_ERROR_UNSUPPORTED_FEATURE /*!< Error when feature is not insupported */ +#define HAL_SD_ERROR_BUSY SDMMC_ERROR_BUSY /*!< Error when transfer process is busy */ +#define HAL_SD_ERROR_DMA SDMMC_ERROR_DMA /*!< Error while DMA transfer */ +#define HAL_SD_ERROR_TIMEOUT SDMMC_ERROR_TIMEOUT /*!< Timeout error */ + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +#define HAL_SD_ERROR_INVALID_CALLBACK SDMMC_ERROR_INVALID_PARAMETER /*!< Invalid callback error */ +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SD_Exported_Constansts_Group2 SD context enumeration + * @{ + */ +#define SD_CONTEXT_NONE 0x00000000U /*!< None */ +#define SD_CONTEXT_READ_SINGLE_BLOCK 0x00000001U /*!< Read single block operation */ +#define SD_CONTEXT_READ_MULTIPLE_BLOCK 0x00000002U /*!< Read multiple blocks operation */ +#define SD_CONTEXT_WRITE_SINGLE_BLOCK 0x00000010U /*!< Write single block operation */ +#define SD_CONTEXT_WRITE_MULTIPLE_BLOCK 0x00000020U /*!< Write multiple blocks operation */ +#define SD_CONTEXT_IT 0x00000008U /*!< Process in Interrupt mode */ +#define SD_CONTEXT_DMA 0x00000080U /*!< Process in DMA mode */ + +/** + * @} + */ + +/** @defgroup SD_Exported_Constansts_Group3 SD Supported Memory Cards + * @{ + */ +#define CARD_SDSC 0x00000000U /*!< SD Standard Capacity <2Go */ +#define CARD_SDHC_SDXC 0x00000001U /*!< SD High Capacity <32Go, SD Extended Capacity <2To */ +#define CARD_SECURED 0x00000003U + +/** + * @} + */ + +/** @defgroup SD_Exported_Constansts_Group4 SD Supported Version + * @{ + */ +#define CARD_V1_X 0x00000000U +#define CARD_V2_X 0x00000001U +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SD_Exported_macros SD Exported Macros + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ +/** @brief Reset SD handle state. + * @param __HANDLE__ : SD handle. + * @retval None + */ +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +#define __HAL_SD_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_SD_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SD_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SD_STATE_RESET) +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + +/** + * @brief Enable the SD device. + * @retval None + */ +#define __HAL_SD_ENABLE(__HANDLE__) __SDIO_ENABLE((__HANDLE__)->Instance) + +/** + * @brief Disable the SD device. + * @retval None + */ +#define __HAL_SD_DISABLE(__HANDLE__) __SDIO_DISABLE((__HANDLE__)->Instance) + +/** + * @brief Enable the SDMMC DMA transfer. + * @retval None + */ +#define __HAL_SD_DMA_ENABLE(__HANDLE__) __SDIO_DMA_ENABLE((__HANDLE__)->Instance) + +/** + * @brief Disable the SDMMC DMA transfer. + * @retval None + */ +#define __HAL_SD_DMA_DISABLE(__HANDLE__) __SDIO_DMA_DISABLE((__HANDLE__)->Instance) + +/** + * @brief Enable the SD device interrupt. + * @param __HANDLE__: SD Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt sources to be enabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __HAL_SD_ENABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_ENABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Disable the SD device interrupt. + * @param __HANDLE__: SD Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt sources to be disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __HAL_SD_DISABLE_IT(__HANDLE__, __INTERRUPT__) __SDIO_DISABLE_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Check whether the specified SD flag is set or not. + * @param __HANDLE__: SD Handle + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDACT: Command transfer in progress + * @arg SDIO_FLAG_TXACT: Data transmit in progress + * @arg SDIO_FLAG_RXACT: Data receive in progress + * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty + * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full + * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full + * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full + * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty + * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty + * @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO + * @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO + * @arg SDIO_FLAG_SDIOIT: SDIO interrupt received + * @retval The new state of SD FLAG (SET or RESET). + */ +#define __HAL_SD_GET_FLAG(__HANDLE__, __FLAG__) __SDIO_GET_FLAG((__HANDLE__)->Instance, (__FLAG__)) + +/** + * @brief Clear the SD's pending flags. + * @param __HANDLE__: SD Handle + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOIT: SDIO interrupt received + * @retval None + */ +#define __HAL_SD_CLEAR_FLAG(__HANDLE__, __FLAG__) __SDIO_CLEAR_FLAG((__HANDLE__)->Instance, (__FLAG__)) + +/** + * @brief Check whether the specified SD interrupt has occurred or not. + * @param __HANDLE__: SD Handle + * @param __INTERRUPT__: specifies the SDMMC interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval The new state of SD IT (SET or RESET). + */ +#define __HAL_SD_GET_IT(__HANDLE__, __INTERRUPT__) __SDIO_GET_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @brief Clear the SD's interrupt pending bits. + * @param __HANDLE__: SD Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __HAL_SD_CLEAR_IT(__HANDLE__, __INTERRUPT__) __SDIO_CLEAR_IT((__HANDLE__)->Instance, (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SD_Exported_Functions SD Exported Functions + * @{ + */ + +/** @defgroup SD_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ +HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_DeInit (SD_HandleTypeDef *hsd); +void HAL_SD_MspInit(SD_HandleTypeDef *hsd); +void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd); +/** + * @} + */ + +/** @defgroup SD_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout); +HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd); +/* Non-Blocking mode: IT */ +HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); +HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks); + +void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd); + +/* Callback in non blocking modes (DMA) */ +void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd); +void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd); +void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd); +void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd); + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +/* SD callback registering/unregistering */ +HAL_StatusTypeDef HAL_SD_RegisterCallback (SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackId, pSD_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SD_UnRegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackId); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SD_Exported_Functions_Group3 Peripheral Control functions + * @{ + */ +HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode); +/** + * @} + */ + +/** @defgroup SD_Exported_Functions_Group4 SD card related functions + * @{ + */ +HAL_StatusTypeDef HAL_SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus); +HAL_SD_CardStateTypeDef HAL_SD_GetCardState(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID); +HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD); +HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus); +HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo); +/** + * @} + */ + +/** @defgroup SD_Exported_Functions_Group5 Peripheral State and Errors functions + * @{ + */ +HAL_SD_StateTypeDef HAL_SD_GetState(SD_HandleTypeDef *hsd); +uint32_t HAL_SD_GetError(SD_HandleTypeDef *hsd); +/** + * @} + */ + +/** @defgroup SD_Exported_Functions_Group6 Perioheral Abort management + * @{ + */ +HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd); +HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd); +/** + * @} + */ + +/* Private types -------------------------------------------------------------*/ +/** @defgroup SD_Private_Types SD Private Types + * @{ + */ + +/** + * @} + */ + +/* Private defines -----------------------------------------------------------*/ +/** @defgroup SD_Private_Defines SD Private Defines + * @{ + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/** @defgroup SD_Private_Variables SD Private Variables + * @{ + */ + +/** + * @} + */ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SD_Private_Constants SD Private Constants + * @{ + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SD_Private_Macros SD Private Macros + * @{ + */ + +/** + * @} + */ + +/* Private functions prototypes ----------------------------------------------*/ +/** @defgroup SD_Private_Functions_Prototypes SD Private Functions Prototypes + * @{ + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SD_Private_Functions SD Private Functions + * @{ + */ + +/** + * @} + */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* SDIO */ + +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_SD_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h new file mode 100644 index 0000000..3d450a0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sdram.h @@ -0,0 +1,238 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sdram.h + * @author MCD Application Team + * @brief Header file of SDRAM 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 STM32F4xx_HAL_SDRAM_H +#define STM32F4xx_HAL_SDRAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMC_Bank5_6) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_fmc.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SDRAM + * @{ + */ + +/* Exported typedef ----------------------------------------------------------*/ + +/** @defgroup SDRAM_Exported_Types SDRAM Exported Types + * @{ + */ + +/** + * @brief HAL SDRAM State structure definition + */ +typedef enum +{ + HAL_SDRAM_STATE_RESET = 0x00U, /*!< SDRAM not yet initialized or disabled */ + HAL_SDRAM_STATE_READY = 0x01U, /*!< SDRAM initialized and ready for use */ + HAL_SDRAM_STATE_BUSY = 0x02U, /*!< SDRAM internal process is ongoing */ + HAL_SDRAM_STATE_ERROR = 0x03U, /*!< SDRAM error state */ + HAL_SDRAM_STATE_WRITE_PROTECTED = 0x04U, /*!< SDRAM device write protected */ + HAL_SDRAM_STATE_PRECHARGED = 0x05U /*!< SDRAM device precharged */ + +} HAL_SDRAM_StateTypeDef; + +/** + * @brief SDRAM handle Structure definition + */ +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) +typedef struct __SDRAM_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +{ + FMC_SDRAM_TypeDef *Instance; /*!< Register base address */ + + FMC_SDRAM_InitTypeDef Init; /*!< SDRAM device configuration parameters */ + + __IO HAL_SDRAM_StateTypeDef State; /*!< SDRAM access state */ + + HAL_LockTypeDef Lock; /*!< SDRAM locking object */ + + DMA_HandleTypeDef *hdma; /*!< Pointer DMA handler */ + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __SDRAM_HandleTypeDef *hsdram); /*!< SDRAM Msp Init callback */ + void (* MspDeInitCallback)(struct __SDRAM_HandleTypeDef *hsdram); /*!< SDRAM Msp DeInit callback */ + void (* RefreshErrorCallback)(struct __SDRAM_HandleTypeDef *hsdram); /*!< SDRAM Refresh Error callback */ + void (* DmaXferCpltCallback)(DMA_HandleTypeDef *hdma); /*!< SDRAM DMA Xfer Complete callback */ + void (* DmaXferErrorCallback)(DMA_HandleTypeDef *hdma); /*!< SDRAM DMA Xfer Error callback */ +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +} SDRAM_HandleTypeDef; + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) +/** + * @brief HAL SDRAM Callback ID enumeration definition + */ +typedef enum +{ + HAL_SDRAM_MSP_INIT_CB_ID = 0x00U, /*!< SDRAM MspInit Callback ID */ + HAL_SDRAM_MSP_DEINIT_CB_ID = 0x01U, /*!< SDRAM MspDeInit Callback ID */ + HAL_SDRAM_REFRESH_ERR_CB_ID = 0x02U, /*!< SDRAM Refresh Error Callback ID */ + HAL_SDRAM_DMA_XFER_CPLT_CB_ID = 0x03U, /*!< SDRAM DMA Xfer Complete Callback ID */ + HAL_SDRAM_DMA_XFER_ERR_CB_ID = 0x04U /*!< SDRAM DMA Xfer Error Callback ID */ +} HAL_SDRAM_CallbackIDTypeDef; + +/** + * @brief HAL SDRAM Callback pointer definition + */ +typedef void (*pSDRAM_CallbackTypeDef)(SDRAM_HandleTypeDef *hsdram); +typedef void (*pSDRAM_DmaCallbackTypeDef)(DMA_HandleTypeDef *hdma); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ + +/** @defgroup SDRAM_Exported_Macros SDRAM Exported Macros + * @{ + */ + +/** @brief Reset SDRAM handle state + * @param __HANDLE__ specifies the SDRAM handle. + * @retval None + */ +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) +#define __HAL_SDRAM_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_SDRAM_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SDRAM_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SDRAM_STATE_RESET) +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup SDRAM_Exported_Functions SDRAM Exported Functions + * @{ + */ + +/** @addtogroup SDRAM_Exported_Functions_Group1 + * @{ + */ + +/* Initialization/de-initialization functions *********************************/ +HAL_StatusTypeDef HAL_SDRAM_Init(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_TimingTypeDef *Timing); +HAL_StatusTypeDef HAL_SDRAM_DeInit(SDRAM_HandleTypeDef *hsdram); +void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram); +void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef *hsdram); + +void HAL_SDRAM_IRQHandler(SDRAM_HandleTypeDef *hsdram); +void HAL_SDRAM_RefreshErrorCallback(SDRAM_HandleTypeDef *hsdram); +void HAL_SDRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma); +void HAL_SDRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma); + +/** + * @} + */ + +/** @addtogroup SDRAM_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ****************************************************/ +HAL_StatusTypeDef HAL_SDRAM_Read_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Write_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pSrcBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Read_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Write_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pSrcBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Read_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Write_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize); + +HAL_StatusTypeDef HAL_SDRAM_Read_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SDRAM_Write_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize); + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) +/* SDRAM callback registering/unregistering */ +HAL_StatusTypeDef HAL_SDRAM_RegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId, + pSDRAM_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SDRAM_UnRegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId); +HAL_StatusTypeDef HAL_SDRAM_RegisterDmaCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId, + pSDRAM_DmaCallbackTypeDef pCallback); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup SDRAM_Exported_Functions_Group3 + * @{ + */ +/* SDRAM Control functions *****************************************************/ +HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Enable(SDRAM_HandleTypeDef *hsdram); +HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Disable(SDRAM_HandleTypeDef *hsdram); +HAL_StatusTypeDef HAL_SDRAM_SendCommand(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command, + uint32_t Timeout); +HAL_StatusTypeDef HAL_SDRAM_ProgramRefreshRate(SDRAM_HandleTypeDef *hsdram, uint32_t RefreshRate); +HAL_StatusTypeDef HAL_SDRAM_SetAutoRefreshNumber(SDRAM_HandleTypeDef *hsdram, uint32_t AutoRefreshNumber); +uint32_t HAL_SDRAM_GetModeStatus(SDRAM_HandleTypeDef *hsdram); + +/** + * @} + */ + +/** @addtogroup SDRAM_Exported_Functions_Group4 + * @{ + */ +/* SDRAM State functions ********************************************************/ +HAL_SDRAM_StateTypeDef HAL_SDRAM_GetState(SDRAM_HandleTypeDef *hsdram); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank5_6 */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_SDRAM_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h new file mode 100644 index 0000000..7aa4ce3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smartcard.h @@ -0,0 +1,755 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_smartcard.h + * @author MCD Application Team + * @brief Header file of SMARTCARD 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 __STM32F4xx_HAL_SMARTCARD_H +#define __STM32F4xx_HAL_SMARTCARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SMARTCARD + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SMARTCARD_Exported_Types SMARTCARD Exported Types + * @{ + */ + +/** + * @brief SMARTCARD Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the SmartCard communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (16 * (hsc->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 SMARTCARD_Word_Length */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref SMARTCARD_Stop_Bits */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref SMARTCARD_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 SMARTCARD_Mode */ + + uint32_t CLKPolarity; /*!< Specifies the steady state of the serial clock. + This parameter can be a value of @ref SMARTCARD_Clock_Polarity */ + + uint32_t CLKPhase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SMARTCARD_Clock_Phase */ + + uint32_t CLKLastBit; /*!< 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 SMARTCARD_Last_Bit */ + + uint32_t Prescaler; /*!< Specifies the SmartCard Prescaler value used for dividing the system clock + to provide the smartcard clock. The value given in the register (5 significant bits) + is multiplied by 2 to give the division factor of the source clock frequency. + This parameter can be a value of @ref SMARTCARD_Prescaler */ + + uint32_t GuardTime; /*!< Specifies the SmartCard Guard Time value in terms of number of baud clocks */ + + uint32_t NACKState; /*!< Specifies the SmartCard NACK Transmission state. + This parameter can be a value of @ref SMARTCARD_NACK_State */ +}SMARTCARD_InitTypeDef; + +/** + * @brief HAL SMARTCARD State structures definition + * @note HAL SMARTCARD State value is a combination of 2 different substates: gState and RxState. + * - gState contains SMARTCARD 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 IP initialization status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP initialized. HAL SMARTCARD Init function already called) + * b4-b3 (not used) + * xx : Should be set to 00 + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP 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 IP initialization status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP 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_SMARTCARD_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized + Value is allowed for gState and RxState */ + HAL_SMARTCARD_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use + Value is allowed for gState and RxState */ + HAL_SMARTCARD_STATE_BUSY = 0x24U, /*!< an internal process is ongoing + Value is allowed for gState only */ + HAL_SMARTCARD_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing + Value is allowed for gState only */ + HAL_SMARTCARD_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing + Value is allowed for RxState only */ + HAL_SMARTCARD_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_SMARTCARD_STATE_TIMEOUT = 0xA0U, /*!< Timeout state + Value is allowed for gState only */ + HAL_SMARTCARD_STATE_ERROR = 0xE0U /*!< Error + Value is allowed for gState only */ +}HAL_SMARTCARD_StateTypeDef; + +/** + * @brief SMARTCARD handle Structure definition + */ +typedef struct __SMARTCARD_HandleTypeDef +{ + USART_TypeDef *Instance; /*!< USART registers base address */ + + SMARTCARD_InitTypeDef Init; /*!< SmartCard communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to SmartCard Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< SmartCard Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< SmartCard Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to SmartCard Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< SmartCard Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< SmartCard Rx Transfer Counter */ + + DMA_HandleTypeDef *hdmatx; /*!< SmartCard Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< SmartCard Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_SMARTCARD_StateTypeDef gState; /*!< SmartCard state information related to global Handle management + and also related to Tx operations. + This parameter can be a value of @ref HAL_SMARTCARD_StateTypeDef */ + + __IO HAL_SMARTCARD_StateTypeDef RxState; /*!< SmartCard state information related to Rx operations. + This parameter can be a value of @ref HAL_SMARTCARD_StateTypeDef */ + + __IO uint32_t ErrorCode; /*!< SmartCard Error code */ + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + void (* TxCpltCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Tx Complete Callback */ + + void (* RxCpltCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Rx Complete Callback */ + + void (* ErrorCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Error Callback */ + + void (* AbortCpltCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Abort Complete Callback */ + + void (* AbortTransmitCpltCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Abort Transmit Complete Callback */ + + void (* AbortReceiveCpltCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Abort Receive Complete Callback */ + + void (* MspInitCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Msp Init callback */ + + void (* MspDeInitCallback)(struct __SMARTCARD_HandleTypeDef *hsc); /*!< SMARTCARD Msp DeInit callback */ +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + +} SMARTCARD_HandleTypeDef; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +/** + * @brief HAL SMARTCARD Callback ID enumeration definition + */ +typedef enum +{ + HAL_SMARTCARD_TX_COMPLETE_CB_ID = 0x00U, /*!< SMARTCARD Tx Complete Callback ID */ + HAL_SMARTCARD_RX_COMPLETE_CB_ID = 0x01U, /*!< SMARTCARD Rx Complete Callback ID */ + HAL_SMARTCARD_ERROR_CB_ID = 0x02U, /*!< SMARTCARD Error Callback ID */ + HAL_SMARTCARD_ABORT_COMPLETE_CB_ID = 0x03U, /*!< SMARTCARD Abort Complete Callback ID */ + HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID = 0x04U, /*!< SMARTCARD Abort Transmit Complete Callback ID */ + HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID = 0x05U, /*!< SMARTCARD Abort Receive Complete Callback ID */ + + HAL_SMARTCARD_MSPINIT_CB_ID = 0x08U, /*!< SMARTCARD MspInit callback ID */ + HAL_SMARTCARD_MSPDEINIT_CB_ID = 0x09U /*!< SMARTCARD MspDeInit callback ID */ + +} HAL_SMARTCARD_CallbackIDTypeDef; + +/** + * @brief HAL SMARTCARD Callback pointer definition + */ +typedef void (*pSMARTCARD_CallbackTypeDef)(SMARTCARD_HandleTypeDef *hsc); /*!< pointer to an SMARTCARD callback function */ + +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SMARTCARD_Exported_Constants SMARTCARD Exported constants + * @{ + */ + +/** @defgroup SMARTCARD_Error_Code SMARTCARD Error Code + * @{ + */ +#define HAL_SMARTCARD_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_SMARTCARD_ERROR_PE 0x00000001U /*!< Parity error */ +#define HAL_SMARTCARD_ERROR_NE 0x00000002U /*!< Noise error */ +#define HAL_SMARTCARD_ERROR_FE 0x00000004U /*!< Frame error */ +#define HAL_SMARTCARD_ERROR_ORE 0x00000008U /*!< Overrun error */ +#define HAL_SMARTCARD_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +#define HAL_SMARTCARD_ERROR_INVALID_CALLBACK 0x00000020U /*!< Invalid Callback error */ +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SMARTCARD_Word_Length SMARTCARD Word Length + * @{ + */ +#define SMARTCARD_WORDLENGTH_9B ((uint32_t)USART_CR1_M) +/** + * @} + */ + +/** @defgroup SMARTCARD_Stop_Bits SMARTCARD Number of Stop Bits + * @{ + */ +#define SMARTCARD_STOPBITS_0_5 ((uint32_t)USART_CR2_STOP_0) +#define SMARTCARD_STOPBITS_1_5 ((uint32_t)(USART_CR2_STOP_0 | USART_CR2_STOP_1)) +/** + * @} + */ + +/** @defgroup SMARTCARD_Parity SMARTCARD Parity + * @{ + */ +#define SMARTCARD_PARITY_EVEN ((uint32_t)USART_CR1_PCE) +#define SMARTCARD_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) +/** + * @} + */ + +/** @defgroup SMARTCARD_Mode SMARTCARD Mode + * @{ + */ +#define SMARTCARD_MODE_RX ((uint32_t)USART_CR1_RE) +#define SMARTCARD_MODE_TX ((uint32_t)USART_CR1_TE) +#define SMARTCARD_MODE_TX_RX ((uint32_t)(USART_CR1_TE |USART_CR1_RE)) +/** + * @} + */ + +/** @defgroup SMARTCARD_Clock_Polarity SMARTCARD Clock Polarity + * @{ + */ +#define SMARTCARD_POLARITY_LOW 0x00000000U +#define SMARTCARD_POLARITY_HIGH ((uint32_t)USART_CR2_CPOL) +/** + * @} + */ + +/** @defgroup SMARTCARD_Clock_Phase SMARTCARD Clock Phase + * @{ + */ +#define SMARTCARD_PHASE_1EDGE 0x00000000U +#define SMARTCARD_PHASE_2EDGE ((uint32_t)USART_CR2_CPHA) +/** + * @} + */ + +/** @defgroup SMARTCARD_Last_Bit SMARTCARD Last Bit + * @{ + */ +#define SMARTCARD_LASTBIT_DISABLE 0x00000000U +#define SMARTCARD_LASTBIT_ENABLE ((uint32_t)USART_CR2_LBCL) +/** + * @} + */ + +/** @defgroup SMARTCARD_NACK_State SMARTCARD NACK State + * @{ + */ +#define SMARTCARD_NACK_ENABLE ((uint32_t)USART_CR3_NACK) +#define SMARTCARD_NACK_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup SMARTCARD_DMA_Requests SMARTCARD DMA requests + * @{ + */ +#define SMARTCARD_DMAREQ_TX ((uint32_t)USART_CR3_DMAT) +#define SMARTCARD_DMAREQ_RX ((uint32_t)USART_CR3_DMAR) +/** + * @} + */ + +/** @defgroup SMARTCARD_Prescaler SMARTCARD Prescaler + * @{ + */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV2 0x00000001U /*!< SYSCLK divided by 2 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV4 0x00000002U /*!< SYSCLK divided by 4 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV6 0x00000003U /*!< SYSCLK divided by 6 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV8 0x00000004U /*!< SYSCLK divided by 8 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV10 0x00000005U /*!< SYSCLK divided by 10 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV12 0x00000006U /*!< SYSCLK divided by 12 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV14 0x00000007U /*!< SYSCLK divided by 14 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV16 0x00000008U /*!< SYSCLK divided by 16 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV18 0x00000009U /*!< SYSCLK divided by 18 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV20 0x0000000AU /*!< SYSCLK divided by 20 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV22 0x0000000BU /*!< SYSCLK divided by 22 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV24 0x0000000CU /*!< SYSCLK divided by 24 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV26 0x0000000DU /*!< SYSCLK divided by 26 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV28 0x0000000EU /*!< SYSCLK divided by 28 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV30 0x0000000FU /*!< SYSCLK divided by 30 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV32 0x00000010U /*!< SYSCLK divided by 32 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV34 0x00000011U /*!< SYSCLK divided by 34 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV36 0x00000012U /*!< SYSCLK divided by 36 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV38 0x00000013U /*!< SYSCLK divided by 38 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV40 0x00000014U /*!< SYSCLK divided by 40 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV42 0x00000015U /*!< SYSCLK divided by 42 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV44 0x00000016U /*!< SYSCLK divided by 44 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV46 0x00000017U /*!< SYSCLK divided by 46 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV48 0x00000018U /*!< SYSCLK divided by 48 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV50 0x00000019U /*!< SYSCLK divided by 50 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV52 0x0000001AU /*!< SYSCLK divided by 52 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV54 0x0000001BU /*!< SYSCLK divided by 54 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV56 0x0000001CU /*!< SYSCLK divided by 56 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV58 0x0000001DU /*!< SYSCLK divided by 58 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV60 0x0000001EU /*!< SYSCLK divided by 60 */ +#define SMARTCARD_PRESCALER_SYSCLK_DIV62 0x0000001FU /*!< SYSCLK divided by 62 */ +/** + * @} + */ + +/** @defgroup SmartCard_Flags SMARTCARD Flags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the SR register + * @{ + */ +#define SMARTCARD_FLAG_TXE ((uint32_t)USART_SR_TXE) +#define SMARTCARD_FLAG_TC ((uint32_t)USART_SR_TC) +#define SMARTCARD_FLAG_RXNE ((uint32_t)USART_SR_RXNE) +#define SMARTCARD_FLAG_IDLE ((uint32_t)USART_SR_IDLE) +#define SMARTCARD_FLAG_ORE ((uint32_t)USART_SR_ORE) +#define SMARTCARD_FLAG_NE ((uint32_t)USART_SR_NE) +#define SMARTCARD_FLAG_FE ((uint32_t)USART_SR_FE) +#define SMARTCARD_FLAG_PE ((uint32_t)USART_SR_PE) +/** + * @} + */ + +/** @defgroup SmartCard_Interrupt_definition SMARTCARD Interrupts Definition + * Elements values convention: 0xY000XXXX + * - XXXX : Interrupt mask in the Y register + * - Y : Interrupt source register (2bits) + * - 01: CR1 register + * - 11: CR3 register + * @{ + */ +#define SMARTCARD_IT_PE ((uint32_t)(SMARTCARD_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) +#define SMARTCARD_IT_TXE ((uint32_t)(SMARTCARD_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) +#define SMARTCARD_IT_TC ((uint32_t)(SMARTCARD_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) +#define SMARTCARD_IT_RXNE ((uint32_t)(SMARTCARD_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) +#define SMARTCARD_IT_IDLE ((uint32_t)(SMARTCARD_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE)) +#define SMARTCARD_IT_ERR ((uint32_t)(SMARTCARD_CR3_REG_INDEX << 28U | USART_CR3_EIE)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SMARTCARD_Exported_Macros SMARTCARD Exported Macros + * @{ + */ + +/** @brief Reset SMARTCARD handle gstate & RxState + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1 +#define __HAL_SMARTCARD_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_SMARTCARD_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_SMARTCARD_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_SMARTCARD_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_SMARTCARD_STATE_RESET; \ + (__HANDLE__)->RxState = HAL_SMARTCARD_STATE_RESET; \ + } while(0U) +#endif /*USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + +/** @brief Flush the Smartcard DR register + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_FLUSH_DRREGISTER(__HANDLE__) ((__HANDLE__)->Instance->DR) + +/** @brief Check whether the specified Smartcard flag is set or not. + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SMARTCARD_FLAG_TXE: Transmit data register empty flag + * @arg SMARTCARD_FLAG_TC: Transmission Complete flag + * @arg SMARTCARD_FLAG_RXNE: Receive data register not empty flag + * @arg SMARTCARD_FLAG_IDLE: Idle Line detection flag + * @arg SMARTCARD_FLAG_ORE: Overrun Error flag + * @arg SMARTCARD_FLAG_NE: Noise Error flag + * @arg SMARTCARD_FLAG_FE: Framing Error flag + * @arg SMARTCARD_FLAG_PE: Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SMARTCARD_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified Smartcard pending flags. + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg SMARTCARD_FLAG_TC: Transmission Complete flag. + * @arg SMARTCARD_FLAG_RXNE: Receive data register not empty flag. + * + * @note PE (Parity error), FE (Framing error), NE (Noise error) and ORE (Overrun + * error) 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_SMARTCARD_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Clear the SMARTCARD PE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR; \ + tmpreg = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg); \ + } while(0U) + +/** @brief Clear the SMARTCARD FE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_CLEAR_FEFLAG(__HANDLE__) __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the SMARTCARD NE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_CLEAR_NEFLAG(__HANDLE__) __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the SMARTCARD ORE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_CLEAR_OREFLAG(__HANDLE__) __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the SMARTCARD IDLE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_CLEAR_IDLEFLAG(__HANDLE__) __HAL_SMARTCARD_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Enable the specified SmartCard interrupt. + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __INTERRUPT__ specifies the SMARTCARD interrupt to enable. + * This parameter can be one of the following values: + * @arg SMARTCARD_IT_TXE: Transmit Data Register empty interrupt + * @arg SMARTCARD_IT_TC: Transmission complete interrupt + * @arg SMARTCARD_IT_RXNE: Receive Data register not empty interrupt + * @arg SMARTCARD_IT_IDLE: Idle line detection interrupt + * @arg SMARTCARD_IT_PE: Parity Error interrupt + * @arg SMARTCARD_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_SMARTCARD_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == SMARTCARD_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & SMARTCARD_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & SMARTCARD_IT_MASK))) + +/** @brief Disable the specified SmartCard interrupt. + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __INTERRUPT__ specifies the SMARTCARD interrupt to disable. + * This parameter can be one of the following values: + * @arg SMARTCARD_IT_TXE: Transmit Data Register empty interrupt + * @arg SMARTCARD_IT_TC: Transmission complete interrupt + * @arg SMARTCARD_IT_RXNE: Receive Data register not empty interrupt + * @arg SMARTCARD_IT_IDLE: Idle line detection interrupt + * @arg SMARTCARD_IT_PE: Parity Error interrupt + * @arg SMARTCARD_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_SMARTCARD_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == SMARTCARD_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & SMARTCARD_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & SMARTCARD_IT_MASK))) + +/** @brief Checks whether the specified SmartCard interrupt has occurred or not. + * @param __HANDLE__ specifies the SmartCard Handle. + * @param __IT__ specifies the SMARTCARD interrupt source to check. + * This parameter can be one of the following values: + * @arg SMARTCARD_IT_TXE: Transmit Data Register empty interrupt + * @arg SMARTCARD_IT_TC: Transmission complete interrupt + * @arg SMARTCARD_IT_RXNE: Receive Data register not empty interrupt + * @arg SMARTCARD_IT_IDLE: Idle line detection interrupt + * @arg SMARTCARD_IT_ERR: Error interrupt + * @arg SMARTCARD_IT_PE: Parity Error interrupt + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_SMARTCARD_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == SMARTCARD_CR1_REG_INDEX)? (__HANDLE__)->Instance->CR1: (__HANDLE__)->Instance->CR3) & (((uint32_t)(__IT__)) & SMARTCARD_IT_MASK)) + +/** @brief Macro to enable the SMARTCARD's one bit sample method + * @param __HANDLE__ specifies the SMARTCARD Handle. + * @retval None + */ +#define __HAL_SMARTCARD_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3|= USART_CR3_ONEBIT) + +/** @brief Macro to disable the SMARTCARD's one bit sample method + * @param __HANDLE__ specifies the SMARTCARD Handle. + * @retval None + */ +#define __HAL_SMARTCARD_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 &= (uint16_t)~((uint16_t)USART_CR3_ONEBIT)) + +/** @brief Enable the USART associated to the SMARTCARD Handle + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable the USART associated to the SMARTCARD Handle + * @param __HANDLE__ specifies the SMARTCARD Handle. + * SMARTCARD Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_SMARTCARD_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) + +/** @brief Macros to enable the SmartCard DMA request. + * @param __HANDLE__ specifies the SmartCard Handle. + * @param __REQUEST__ specifies the SmartCard DMA request. + * This parameter can be one of the following values: + * @arg SMARTCARD_DMAREQ_TX: SmartCard DMA transmit request + * @arg SMARTCARD_DMAREQ_RX: SmartCard DMA receive request + * @retval None + */ +#define __HAL_SMARTCARD_DMA_REQUEST_ENABLE(__HANDLE__, __REQUEST__) ((__HANDLE__)->Instance->CR3 |= (__REQUEST__)) + +/** @brief Macros to disable the SmartCard DMA request. + * @param __HANDLE__ specifies the SmartCard Handle. + * @param __REQUEST__ specifies the SmartCard DMA request. + * This parameter can be one of the following values: + * @arg SMARTCARD_DMAREQ_TX: SmartCard DMA transmit request + * @arg SMARTCARD_DMAREQ_RX: SmartCard DMA receive request + * @retval None + */ +#define __HAL_SMARTCARD_DMA_REQUEST_DISABLE(__HANDLE__, __REQUEST__) ((__HANDLE__)->Instance->CR3 &= ~(__REQUEST__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SMARTCARD_Exported_Functions + * @{ + */ + +/** @addtogroup SMARTCARD_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_ReInit(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_DeInit(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_MspDeInit(SMARTCARD_HandleTypeDef *hsc); +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +/* Callbacks Register/UnRegister functions ***********************************/ +HAL_StatusTypeDef HAL_SMARTCARD_RegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID, pSMARTCARD_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SMARTCARD_UnRegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup SMARTCARD_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_SMARTCARD_Transmit(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SMARTCARD_Receive(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SMARTCARD_Transmit_DMA(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SMARTCARD_Receive_DMA(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_SMARTCARD_Abort(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_Abort_IT(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit_IT(SMARTCARD_HandleTypeDef *hsc); +HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive_IT(SMARTCARD_HandleTypeDef *hsc); + +void HAL_SMARTCARD_IRQHandler(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_TxCpltCallback(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_RxCpltCallback(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_ErrorCallback(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_AbortCpltCallback(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_AbortTransmitCpltCallback(SMARTCARD_HandleTypeDef *hsc); +void HAL_SMARTCARD_AbortReceiveCpltCallback(SMARTCARD_HandleTypeDef *hsc); +/** + * @} + */ + +/** @addtogroup SMARTCARD_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_SMARTCARD_StateTypeDef HAL_SMARTCARD_GetState(const SMARTCARD_HandleTypeDef *hsc); +uint32_t HAL_SMARTCARD_GetError(const SMARTCARD_HandleTypeDef *hsc); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SMARTCARD_Private_Constants SMARTCARD Private Constants + * @{ + */ + +/** @brief SMARTCARD interruptions flag mask + * + */ +#define SMARTCARD_IT_MASK ((uint32_t) USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | \ + USART_CR1_IDLEIE | USART_CR3_EIE ) + +#define SMARTCARD_CR1_REG_INDEX 1U +#define SMARTCARD_CR3_REG_INDEX 3U +/** + * @} + */ + +/* Private macros --------------------------------------------------------*/ +/** @defgroup SMARTCARD_Private_Macros SMARTCARD Private Macros + * @{ + */ +#define IS_SMARTCARD_WORD_LENGTH(LENGTH) ((LENGTH) == SMARTCARD_WORDLENGTH_9B) +#define IS_SMARTCARD_STOPBITS(STOPBITS) (((STOPBITS) == SMARTCARD_STOPBITS_0_5) || \ + ((STOPBITS) == SMARTCARD_STOPBITS_1_5)) +#define IS_SMARTCARD_PARITY(PARITY) (((PARITY) == SMARTCARD_PARITY_EVEN) || \ + ((PARITY) == SMARTCARD_PARITY_ODD)) +#define IS_SMARTCARD_MODE(MODE) ((((MODE) & 0x0000FFF3U) == 0x00U) && ((MODE) != 0x000000U)) +#define IS_SMARTCARD_POLARITY(CPOL) (((CPOL) == SMARTCARD_POLARITY_LOW) || ((CPOL) == SMARTCARD_POLARITY_HIGH)) +#define IS_SMARTCARD_PHASE(CPHA) (((CPHA) == SMARTCARD_PHASE_1EDGE) || ((CPHA) == SMARTCARD_PHASE_2EDGE)) +#define IS_SMARTCARD_LASTBIT(LASTBIT) (((LASTBIT) == SMARTCARD_LASTBIT_DISABLE) || \ + ((LASTBIT) == SMARTCARD_LASTBIT_ENABLE)) +#define IS_SMARTCARD_NACK_STATE(NACK) (((NACK) == SMARTCARD_NACK_ENABLE) || \ + ((NACK) == SMARTCARD_NACK_DISABLE)) +#define IS_SMARTCARD_BAUDRATE(BAUDRATE) ((BAUDRATE) < 10500001U) + +#define SMARTCARD_DIV(__PCLK__, __BAUD__) ((uint32_t)((((uint64_t)(__PCLK__))*25U)/(4U*((uint64_t)(__BAUD__))))) +#define SMARTCARD_DIVMANT(__PCLK__, __BAUD__) (SMARTCARD_DIV((__PCLK__), (__BAUD__))/100U) +#define SMARTCARD_DIVFRAQ(__PCLK__, __BAUD__) ((((SMARTCARD_DIV((__PCLK__), (__BAUD__)) - (SMARTCARD_DIVMANT((__PCLK__), (__BAUD__)) * 100U)) * 16U) + 50U) / 100U) +/* SMARTCARD BRR = mantissa + overflow + fraction + = (SMARTCARD DIVMANT << 4) + (SMARTCARD DIVFRAQ & 0xF0) + (SMARTCARD DIVFRAQ & 0x0FU) */ +#define SMARTCARD_BRR(__PCLK__, __BAUD__) (((SMARTCARD_DIVMANT((__PCLK__), (__BAUD__)) << 4U) + \ + (SMARTCARD_DIVFRAQ((__PCLK__), (__BAUD__)) & 0xF0U)) + \ + (SMARTCARD_DIVFRAQ((__PCLK__), (__BAUD__)) & 0x0FU)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SMARTCARD_Private_Functions SMARTCARD Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_SMARTCARD_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h new file mode 100644 index 0000000..ea92afa --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_smbus.h @@ -0,0 +1,731 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_smbus.h + * @author MCD Application Team + * @brief Header file of SMBUS 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 __STM32F4xx_HAL_SMBUS_H +#define __STM32F4xx_HAL_SMBUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SMBUS + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SMBUS_Exported_Types SMBUS Exported Types + * @{ + */ + +/** + * @brief SMBUS Configuration Structure definition + */ +typedef struct +{ + uint32_t ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 100kHz */ + + uint32_t AnalogFilter; /*!< Specifies if Analog Filter is enable or not. + This parameter can be a value of @ref SMBUS_Analog_Filter */ + + uint32_t OwnAddress1; /*!< Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint32_t AddressingMode; /*!< Specifies if 7-bit or 10-bit addressing mode is selected. + This parameter can be a value of @ref SMBUS_addressing_mode */ + + uint32_t DualAddressMode; /*!< Specifies if dual addressing mode is selected. + This parameter can be a value of @ref SMBUS_dual_addressing_mode */ + + uint32_t OwnAddress2; /*!< Specifies the second device own address if dual addressing mode is + selected. This parameter can be a 7-bit address. */ + + uint32_t GeneralCallMode; /*!< Specifies if general call mode is selected. + This parameter can be a value of @ref SMBUS_general_call_addressing_mode */ + + uint32_t NoStretchMode; /*!< Specifies if nostretch mode is selected. + This parameter can be a value of @ref SMBUS_nostretch_mode */ + + uint32_t PacketErrorCheckMode; /*!< Specifies if Packet Error Check mode is selected. + This parameter can be a value of @ref SMBUS_packet_error_check_mode */ + + uint32_t PeripheralMode; /*!< Specifies which mode of Periphal is selected. + This parameter can be a value of @ref SMBUS_peripheral_mode */ + +} SMBUS_InitTypeDef; + +/** + * @brief HAL State structure definition + * @note HAL SMBUS State value coding follow below described bitmap : + * b7-b6 Error information + * 00 : No Error + * 01 : Abort (Abort user request on going) + * 10 : Timeout + * 11 : Error + * b5 IP initialisation status + * 0 : Reset (IP not initialized) + * 1 : Init done (IP initialized and ready to use. HAL SMBUS Init function called) + * b4 (not used) + * x : Should be set to 0 + * b3 + * 0 : Ready or Busy (No Listen mode ongoing) + * 1 : Listen (IP in Address Listen Mode) + * b2 Intrinsic process state + * 0 : Ready + * 1 : Busy (IP busy with some configuration or internal operations) + * b1 Rx state + * 0 : Ready (no Rx operation ongoing) + * 1 : Busy (Rx operation ongoing) + * b0 Tx state + * 0 : Ready (no Tx operation ongoing) + * 1 : Busy (Tx operation ongoing) + */ +typedef enum +{ + + HAL_SMBUS_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_SMBUS_STATE_READY = 0x20U, /*!< Peripheral Initialized and ready for use */ + HAL_SMBUS_STATE_BUSY = 0x24U, /*!< An internal process is ongoing */ + HAL_SMBUS_STATE_BUSY_TX = 0x21U, /*!< Data Transmission process is ongoing */ + HAL_SMBUS_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_SMBUS_STATE_LISTEN = 0x28U, /*!< Address Listen Mode is ongoing */ + HAL_SMBUS_STATE_BUSY_TX_LISTEN = 0x29U, /*!< Address Listen Mode and Data Transmission + process is ongoing */ + HAL_SMBUS_STATE_BUSY_RX_LISTEN = 0x2AU, /*!< Address Listen Mode and Data Reception + process is ongoing */ + HAL_SMBUS_STATE_ABORT = 0x60U, /*!< Abort user request ongoing */ + HAL_SMBUS_STATE_TIMEOUT = 0xA0U, /*!< Timeout state */ + HAL_SMBUS_STATE_ERROR = 0xE0U /*!< Error */ +} HAL_SMBUS_StateTypeDef; + +/** + * @brief HAL Mode structure definition + * @note HAL SMBUS Mode value coding follow below described bitmap : + * b7 (not used) + * x : Should be set to 0 + * b6 (not used) + * x : Should be set to 0 + * b5 + * 0 : None + * 1 : Slave (HAL SMBUS communication is in Slave/Device Mode) + * b4 + * 0 : None + * 1 : Master (HAL SMBUS communication is in Master/Host Mode) + * b3-b2-b1-b0 (not used) + * xxxx : Should be set to 0000 + */ +typedef enum +{ + HAL_SMBUS_MODE_NONE = 0x00U, /*!< No SMBUS communication on going */ + HAL_SMBUS_MODE_MASTER = 0x10U, /*!< SMBUS communication is in Master Mode */ + HAL_SMBUS_MODE_SLAVE = 0x20U, /*!< SMBUS communication is in Slave Mode */ + +} HAL_SMBUS_ModeTypeDef; + +/** + * @brief SMBUS handle Structure definition + */ +typedef struct __SMBUS_HandleTypeDef +{ + I2C_TypeDef *Instance; /*!< SMBUS registers base address */ + + SMBUS_InitTypeDef Init; /*!< SMBUS communication parameters */ + + uint8_t *pBuffPtr; /*!< Pointer to SMBUS transfer buffer */ + + uint16_t XferSize; /*!< SMBUS transfer size */ + + __IO uint16_t XferCount; /*!< SMBUS transfer counter */ + + __IO uint32_t XferOptions; /*!< SMBUS transfer options this parameter can + be a value of @ref SMBUS_OPTIONS */ + + __IO uint32_t PreviousState; /*!< SMBUS communication Previous state and mode + context for internal usage */ + + HAL_LockTypeDef Lock; /*!< SMBUS locking object */ + + __IO HAL_SMBUS_StateTypeDef State; /*!< SMBUS communication state */ + + __IO HAL_SMBUS_ModeTypeDef Mode; /*!< SMBUS communication mode */ + + __IO uint32_t ErrorCode; /*!< SMBUS Error code */ + + __IO uint32_t Devaddress; /*!< SMBUS Target device address */ + + __IO uint32_t EventCount; /*!< SMBUS Event counter */ + + uint8_t XferPEC; /*!< SMBUS PEC data in reception mode */ + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + void (* MasterTxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Master Tx Transfer completed callback */ + void (* MasterRxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Master Rx Transfer completed callback */ + void (* SlaveTxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Slave Tx Transfer completed callback */ + void (* SlaveRxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Slave Rx Transfer completed callback */ + void (* ListenCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Listen Complete callback */ + void (* MemTxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Memory Tx Transfer completed callback */ + void (* MemRxCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Memory Rx Transfer completed callback */ + void (* ErrorCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Error callback */ + void (* AbortCpltCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Abort callback */ + void (* AddrCallback)(struct __SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< SMBUS Slave Address Match callback */ + void (* MspInitCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Msp Init callback */ + void (* MspDeInitCallback)(struct __SMBUS_HandleTypeDef *hsmbus); /*!< SMBUS Msp DeInit callback */ + +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ +} SMBUS_HandleTypeDef; + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) +/** + * @brief HAL SMBUS Callback ID enumeration definition + */ +typedef enum +{ + HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID = 0x00U, /*!< SMBUS Master Tx Transfer completed callback ID */ + HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID = 0x01U, /*!< SMBUS Master Rx Transfer completed callback ID */ + HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID = 0x02U, /*!< SMBUS Slave Tx Transfer completed callback ID */ + HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID = 0x03U, /*!< SMBUS Slave Rx Transfer completed callback ID */ + HAL_SMBUS_LISTEN_COMPLETE_CB_ID = 0x04U, /*!< SMBUS Listen Complete callback ID */ + HAL_SMBUS_ERROR_CB_ID = 0x07U, /*!< SMBUS Error callback ID */ + HAL_SMBUS_ABORT_CB_ID = 0x08U, /*!< SMBUS Abort callback ID */ + HAL_SMBUS_MSPINIT_CB_ID = 0x09U, /*!< SMBUS Msp Init callback ID */ + HAL_SMBUS_MSPDEINIT_CB_ID = 0x0AU /*!< SMBUS Msp DeInit callback ID */ + +} HAL_SMBUS_CallbackIDTypeDef; + +/** + * @brief HAL SMBUS Callback pointer definition + */ +typedef void (*pSMBUS_CallbackTypeDef)(SMBUS_HandleTypeDef *hsmbus); /*!< pointer to an I2C callback function */ +typedef void (*pSMBUS_AddrCallbackTypeDef)(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< pointer to an I2C Address Match callback function */ + +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SMBUS_Exported_Constants SMBUS Exported Constants + * @{ + */ + +/** @defgroup SMBUS_Error_Code_definition SMBUS Error Code + * @brief SMBUS Error Code + * @{ + */ +#define HAL_SMBUS_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_SMBUS_ERROR_BERR 0x00000001U /*!< BERR error */ +#define HAL_SMBUS_ERROR_ARLO 0x00000002U /*!< ARLO error */ +#define HAL_SMBUS_ERROR_AF 0x00000004U /*!< AF error */ +#define HAL_SMBUS_ERROR_OVR 0x00000008U /*!< OVR error */ +#define HAL_SMBUS_ERROR_TIMEOUT 0x00000010U /*!< Timeout Error */ +#define HAL_SMBUS_ERROR_ALERT 0x00000020U /*!< Alert error */ +#define HAL_SMBUS_ERROR_PECERR 0x00000040U /*!< PEC error */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) +#define HAL_SMBUS_ERROR_INVALID_CALLBACK 0x00000080U /*!< Invalid Callback error */ +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SMBUS_Analog_Filter SMBUS Analog Filter + * @{ + */ +#define SMBUS_ANALOGFILTER_ENABLE 0x00000000U +#define SMBUS_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF +/** + * @} + */ + +/** @defgroup SMBUS_addressing_mode SMBUS addressing mode + * @{ + */ +#define SMBUS_ADDRESSINGMODE_7BIT 0x00004000U +#define SMBUS_ADDRESSINGMODE_10BIT (I2C_OAR1_ADDMODE | 0x00004000U) +/** + * @} + */ + +/** @defgroup SMBUS_dual_addressing_mode SMBUS dual addressing mode + * @{ + */ +#define SMBUS_DUALADDRESS_DISABLE 0x00000000U +#define SMBUS_DUALADDRESS_ENABLE I2C_OAR2_ENDUAL +/** + * @} + */ + +/** @defgroup SMBUS_general_call_addressing_mode SMBUS general call addressing mode + * @{ + */ +#define SMBUS_GENERALCALL_DISABLE 0x00000000U +#define SMBUS_GENERALCALL_ENABLE I2C_CR1_ENGC +/** + * @} + */ + +/** @defgroup SMBUS_nostretch_mode SMBUS nostretch mode + * @{ + */ +#define SMBUS_NOSTRETCH_DISABLE 0x00000000U +#define SMBUS_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH +/** + * @} + */ + +/** @defgroup SMBUS_packet_error_check_mode SMBUS packet error check mode + * @{ + */ +#define SMBUS_PEC_DISABLE 0x00000000U +#define SMBUS_PEC_ENABLE I2C_CR1_ENPEC +/** + * @} + */ + +/** @defgroup SMBUS_peripheral_mode SMBUS peripheral mode +* @{ +*/ +#define SMBUS_PERIPHERAL_MODE_SMBUS_HOST (uint32_t)(I2C_CR1_SMBUS | I2C_CR1_SMBTYPE | I2C_CR1_ENARP) +#define SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE I2C_CR1_SMBUS +#define SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE_ARP (uint32_t)(I2C_CR1_SMBUS | I2C_CR1_ENARP) +/** +* @} +*/ + +/** @defgroup SMBUS_XferDirection_definition SMBUS XferDirection definition + * @{ + */ +#define SMBUS_DIRECTION_RECEIVE 0x00000000U +#define SMBUS_DIRECTION_TRANSMIT 0x00000001U +/** + * @} + */ + +/** @defgroup SMBUS_XferOptions_definition SMBUS XferOptions definition + * @{ + */ +#define SMBUS_FIRST_FRAME 0x00000001U +#define SMBUS_NEXT_FRAME 0x00000002U +#define SMBUS_FIRST_AND_LAST_FRAME_NO_PEC 0x00000003U +#define SMBUS_LAST_FRAME_NO_PEC 0x00000004U +#define SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC 0x00000005U +#define SMBUS_LAST_FRAME_WITH_PEC 0x00000006U +/** + * @} + */ + +/** @defgroup SMBUS_Interrupt_configuration_definition SMBUS Interrupt configuration definition + * @{ + */ +#define SMBUS_IT_BUF I2C_CR2_ITBUFEN +#define SMBUS_IT_EVT I2C_CR2_ITEVTEN +#define SMBUS_IT_ERR I2C_CR2_ITERREN +/** + * @} + */ + +/** @defgroup SMBUS_Flag_definition SMBUS Flag definition + * @{ + */ +#define SMBUS_FLAG_SMBALERT 0x00018000U +#define SMBUS_FLAG_TIMEOUT 0x00014000U +#define SMBUS_FLAG_PECERR 0x00011000U +#define SMBUS_FLAG_OVR 0x00010800U +#define SMBUS_FLAG_AF 0x00010400U +#define SMBUS_FLAG_ARLO 0x00010200U +#define SMBUS_FLAG_BERR 0x00010100U +#define SMBUS_FLAG_TXE 0x00010080U +#define SMBUS_FLAG_RXNE 0x00010040U +#define SMBUS_FLAG_STOPF 0x00010010U +#define SMBUS_FLAG_ADD10 0x00010008U +#define SMBUS_FLAG_BTF 0x00010004U +#define SMBUS_FLAG_ADDR 0x00010002U +#define SMBUS_FLAG_SB 0x00010001U +#define SMBUS_FLAG_DUALF 0x00100080U +#define SMBUS_FLAG_SMBHOST 0x00100040U +#define SMBUS_FLAG_SMBDEFAULT 0x00100020U +#define SMBUS_FLAG_GENCALL 0x00100010U +#define SMBUS_FLAG_TRA 0x00100004U +#define SMBUS_FLAG_BUSY 0x00100002U +#define SMBUS_FLAG_MSL 0x00100001U +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SMBUS_Exported_Macros SMBUS Exported Macros + * @{ + */ + +/** @brief Reset SMBUS handle state + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @retval None + */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) +#define __HAL_SMBUS_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_SMBUS_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SMBUS_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SMBUS_STATE_RESET) +#endif + +/** @brief Enable or disable the specified SMBUS interrupts. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg SMBUS_IT_BUF: Buffer interrupt enable + * @arg SMBUS_IT_EVT: Event interrupt enable + * @arg SMBUS_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_SMBUS_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 |= (__INTERRUPT__)) +#define __HAL_SMBUS_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->CR2 &= (~(__INTERRUPT__))) + +/** @brief Checks if the specified SMBUS interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @param __INTERRUPT__ specifies the SMBUS interrupt source to check. + * This parameter can be one of the following values: + * @arg SMBUS_IT_BUF: Buffer interrupt enable + * @arg SMBUS_IT_EVT: Event interrupt enable + * @arg SMBUS_IT_ERR: Error interrupt enable + * @retval The new state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_SMBUS_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified SMBUS flag is set or not. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SMBUS_FLAG_SMBALERT: SMBus Alert flag + * @arg SMBUS_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg SMBUS_FLAG_PECERR: PEC error in reception flag + * @arg SMBUS_FLAG_OVR: Overrun/Underrun flag + * @arg SMBUS_FLAG_AF: Acknowledge failure flag + * @arg SMBUS_FLAG_ARLO: Arbitration lost flag + * @arg SMBUS_FLAG_BERR: Bus error flag + * @arg SMBUS_FLAG_TXE: Data register empty flag + * @arg SMBUS_FLAG_RXNE: Data register not empty flag + * @arg SMBUS_FLAG_STOPF: Stop detection flag + * @arg SMBUS_FLAG_ADD10: 10-bit header sent flag + * @arg SMBUS_FLAG_BTF: Byte transfer finished flag + * @arg SMBUS_FLAG_ADDR: Address sent flag + * Address matched flag + * @arg SMBUS_FLAG_SB: Start bit flag + * @arg SMBUS_FLAG_DUALF: Dual flag + * @arg SMBUS_FLAG_SMBHOST: SMBus host header + * @arg SMBUS_FLAG_SMBDEFAULT: SMBus default header + * @arg SMBUS_FLAG_GENCALL: General call header flag + * @arg SMBUS_FLAG_TRA: Transmitter/Receiver flag + * @arg SMBUS_FLAG_BUSY: Bus busy flag + * @arg SMBUS_FLAG_MSL: Master/Slave flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SMBUS_GET_FLAG(__HANDLE__, __FLAG__) ((((uint8_t)((__FLAG__) >> 16U)) == 0x01U)?((((__HANDLE__)->Instance->SR1) & ((__FLAG__) & SMBUS_FLAG_MASK)) == ((__FLAG__) & SMBUS_FLAG_MASK)): \ + ((((__HANDLE__)->Instance->SR2) & ((__FLAG__) & SMBUS_FLAG_MASK)) == ((__FLAG__) & SMBUS_FLAG_MASK))) + +/** @brief Clears the SMBUS pending flags which are cleared by writing 0 in a specific bit. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @param __FLAG__ specifies the flag to clear. + * This parameter can be any combination of the following values: + * @arg SMBUS_FLAG_SMBALERT: SMBus Alert flag + * @arg SMBUS_FLAG_TIMEOUT: Timeout or Tlow error flag + * @arg SMBUS_FLAG_PECERR: PEC error in reception flag + * @arg SMBUS_FLAG_OVR: Overrun/Underrun flag (Slave mode) + * @arg SMBUS_FLAG_AF: Acknowledge failure flag + * @arg SMBUS_FLAG_ARLO: Arbitration lost flag (Master mode) + * @arg SMBUS_FLAG_BERR: Bus error flag + * @retval None + */ +#define __HAL_SMBUS_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR1 = ~((__FLAG__) & SMBUS_FLAG_MASK)) + +/** @brief Clears the SMBUS ADDR pending flag. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @retval None + */ +#define __HAL_SMBUS_CLEAR_ADDRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + tmpreg = (__HANDLE__)->Instance->SR2; \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Clears the SMBUS STOPF pending flag. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUS where x: 1, 2, or 3 to select the SMBUS peripheral. + * @retval None + */ +#define __HAL_SMBUS_CLEAR_STOPFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR1; \ + (__HANDLE__)->Instance->CR1 |= I2C_CR1_PE; \ + UNUSED(tmpreg); \ + } while(0) + +/** @brief Enable the SMBUS peripheral. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUSx where x: 1 or 2 to select the SMBUS peripheral. + * @retval None + */ +#define __HAL_SMBUS_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= I2C_CR1_PE) + +/** @brief Disable the SMBUS peripheral. + * @param __HANDLE__ specifies the SMBUS Handle. + * This parameter can be SMBUSx where x: 1 or 2 to select the SMBUS peripheral. + * @retval None + */ +#define __HAL_SMBUS_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~I2C_CR1_PE) + +/** @brief Generate a Non-Acknowledge SMBUS peripheral in Slave mode. + * @param __HANDLE__ specifies the SMBUS Handle. + * @retval None + */ +#define __HAL_SMBUS_GENERATE_NACK(__HANDLE__) (CLEAR_BIT((__HANDLE__)->Instance->CR1, I2C_CR1_ACK)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SMBUS_Exported_Functions + * @{ + */ + +/** @addtogroup SMBUS_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_SMBUS_Init(SMBUS_HandleTypeDef *hsmbus); +HAL_StatusTypeDef HAL_SMBUS_DeInit(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_MspInit(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef *hsmbus); + +/* Callbacks Register/UnRegister functions ************************************/ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID, pSMBUS_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID); + +HAL_StatusTypeDef HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus, pSMBUS_AddrCallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup SMBUS_Exported_Functions_Group2 Input and Output operation functions + * @{ + */ + +/* IO operation functions *****************************************************/ +/** @addtogroup Blocking_mode_Polling Blocking mode Polling + * @{ + */ +/******* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout); +/** + * @} + */ + +/** @addtogroup Non-Blocking_mode_Interrupt Non-Blocking mode Interrupt + * @{ + */ +/******* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress); +HAL_StatusTypeDef HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions); +HAL_StatusTypeDef HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions); + +HAL_StatusTypeDef HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef *hsmbus); +HAL_StatusTypeDef HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef *hsmbus); +HAL_StatusTypeDef HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef *hsmbus); +HAL_StatusTypeDef HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef *hsmbus); + +/****** Filter Configuration functions */ +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +HAL_StatusTypeDef HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t AnalogFilter); +HAL_StatusTypeDef HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t DigitalFilter); +#endif +/** + * @} + */ + +/** @addtogroup SMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ +/******* SMBUS IRQHandler and Callbacks used in non blocking modes (Interrupt) */ +void HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode); +void HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef *hsmbus); +void HAL_SMBUS_AbortCpltCallback(SMBUS_HandleTypeDef *hsmbus); + +/** + * @} + */ + +/** @addtogroup SMBUS_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @{ + */ + +/* Peripheral State, mode and Errors functions **************************************************/ +HAL_SMBUS_StateTypeDef HAL_SMBUS_GetState(SMBUS_HandleTypeDef *hsmbus); +HAL_SMBUS_ModeTypeDef HAL_SMBUS_GetMode(SMBUS_HandleTypeDef *hsmbus); +uint32_t HAL_SMBUS_GetError(SMBUS_HandleTypeDef *hsmbus); + +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SMBUS_Private_Constants SMBUS Private Constants + * @{ + */ +#define SMBUS_FLAG_MASK 0x0000FFFFU +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SMBUS_Private_Macros SMBUS Private Macros + * @{ + */ + +#define SMBUS_FREQRANGE(__PCLK__) ((__PCLK__)/1000000U) + +#define SMBUS_RISE_TIME(__FREQRANGE__) ( ((__FREQRANGE__) + 1U)) + +#define SMBUS_SPEED_STANDARD(__PCLK__, __SPEED__) (((((__PCLK__)/((__SPEED__) << 1U)) & I2C_CCR_CCR) < 4U)? 4U:((__PCLK__) / ((__SPEED__) << 1U))) + +#define SMBUS_7BIT_ADD_WRITE(__ADDRESS__) ((uint8_t)((__ADDRESS__) & (~I2C_OAR1_ADD0))) + +#define SMBUS_7BIT_ADD_READ(__ADDRESS__) ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0)) + +#define SMBUS_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)0x00FF))) + +#define SMBUS_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)0x00F0))) + +#define SMBUS_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)0x0300)) >> 7) | (uint16_t)(0x00F1)))) + +#define SMBUS_GET_PEC_MODE(__HANDLE__) ((__HANDLE__)->Instance->CR1 & I2C_CR1_ENPEC) + +#define SMBUS_GET_PEC_VALUE(__HANDLE__) ((__HANDLE__)->XferPEC) + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +#define IS_SMBUS_ANALOG_FILTER(FILTER) (((FILTER) == SMBUS_ANALOGFILTER_ENABLE) || \ + ((FILTER) == SMBUS_ANALOGFILTER_DISABLE)) +#define IS_SMBUS_DIGITAL_FILTER(FILTER) ((FILTER) <= 0x0000000FU) +#endif +#define IS_SMBUS_ADDRESSING_MODE(ADDRESS) (((ADDRESS) == SMBUS_ADDRESSINGMODE_7BIT) || \ + ((ADDRESS) == SMBUS_ADDRESSINGMODE_10BIT)) + +#define IS_SMBUS_DUAL_ADDRESS(ADDRESS) (((ADDRESS) == SMBUS_DUALADDRESS_DISABLE) || \ + ((ADDRESS) == SMBUS_DUALADDRESS_ENABLE)) + +#define IS_SMBUS_GENERAL_CALL(CALL) (((CALL) == SMBUS_GENERALCALL_DISABLE) || \ + ((CALL) == SMBUS_GENERALCALL_ENABLE)) + +#define IS_SMBUS_NO_STRETCH(STRETCH) (((STRETCH) == SMBUS_NOSTRETCH_DISABLE) || \ + ((STRETCH) == SMBUS_NOSTRETCH_ENABLE)) + +#define IS_SMBUS_PEC(PEC) (((PEC) == SMBUS_PEC_DISABLE) || \ + ((PEC) == SMBUS_PEC_ENABLE)) + +#define IS_SMBUS_PERIPHERAL_MODE(MODE) (((MODE) == SMBUS_PERIPHERAL_MODE_SMBUS_HOST) || \ + ((MODE) == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE) || \ + ((MODE) == SMBUS_PERIPHERAL_MODE_SMBUS_SLAVE_ARP)) + +#define IS_SMBUS_CLOCK_SPEED(SPEED) (((SPEED) > 0U) && ((SPEED) <= 100000U)) + +#define IS_SMBUS_OWN_ADDRESS1(ADDRESS1) (((ADDRESS1) & 0xFFFFFC00U) == 0U) + +#define IS_SMBUS_OWN_ADDRESS2(ADDRESS2) (((ADDRESS2) & 0xFFFFFF01U) == 0U) + +#define IS_SMBUS_TRANSFER_OPTIONS_REQUEST(REQUEST) (((REQUEST) == SMBUS_FIRST_FRAME) || \ + ((REQUEST) == SMBUS_NEXT_FRAME) || \ + ((REQUEST) == SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || \ + ((REQUEST) == SMBUS_LAST_FRAME_NO_PEC) || \ + ((REQUEST) == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || \ + ((REQUEST) == SMBUS_LAST_FRAME_WITH_PEC)) + +/** + * @} + */ + +/* Private Functions ---------------------------------------------------------*/ +/** @defgroup SMBUS_Private_Functions SMBUS Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** +* @} +*/ + +#ifdef __cplusplus +} +#endif + + +#endif /* __STM32F4xx_HAL_SMBUS_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h new file mode 100644 index 0000000..7ea04aa --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spdifrx.h @@ -0,0 +1,604 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_spdifrx.h + * @author MCD Application Team + * @brief Header file of SPDIFRX 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 STM32F4xx_HAL_SPDIFRX_H +#define STM32F4xx_HAL_SPDIFRX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined(STM32F446xx) +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (SPDIFRX) + +/** @addtogroup SPDIFRX + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SPDIFRX_Exported_Types SPDIFRX Exported Types + * @{ + */ + +/** + * @brief SPDIFRX Init structure definition + */ +typedef struct +{ + uint32_t InputSelection; /*!< Specifies the SPDIF input selection. + This parameter can be a value of @ref SPDIFRX_Input_Selection */ + + uint32_t Retries; /*!< Specifies the Maximum allowed re-tries during synchronization phase. + This parameter can be a value of @ref SPDIFRX_Max_Retries */ + + uint32_t WaitForActivity; /*!< Specifies the wait for activity on SPDIF selected input. + This parameter can be a value of @ref SPDIFRX_Wait_For_Activity. */ + + uint32_t ChannelSelection; /*!< Specifies whether the control flow will take the channel status from channel A or B. + This parameter can be a value of @ref SPDIFRX_Channel_Selection */ + + uint32_t DataFormat; /*!< Specifies the Data samples format (LSB, MSB, ...). + This parameter can be a value of @ref SPDIFRX_Data_Format */ + + uint32_t StereoMode; /*!< Specifies whether the peripheral is in stereo or mono mode. + This parameter can be a value of @ref SPDIFRX_Stereo_Mode */ + + uint32_t PreambleTypeMask; /*!< Specifies whether The preamble type bits are copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_PT_Mask */ + + uint32_t ChannelStatusMask; /*!< Specifies whether the channel status and user bits are copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_ChannelStatus_Mask */ + + uint32_t ValidityBitMask; /*!< Specifies whether the validity bit is copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_V_Mask */ + + uint32_t ParityErrorMask; /*!< Specifies whether the parity error bit is copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_PE_Mask */ +} SPDIFRX_InitTypeDef; + +/** + * @brief SPDIFRX SetDataFormat structure definition + */ +typedef struct +{ + uint32_t DataFormat; /*!< Specifies the Data samples format (LSB, MSB, ...). + This parameter can be a value of @ref SPDIFRX_Data_Format */ + + uint32_t StereoMode; /*!< Specifies whether the peripheral is in stereo or mono mode. + This parameter can be a value of @ref SPDIFRX_Stereo_Mode */ + + uint32_t PreambleTypeMask; /*!< Specifies whether The preamble type bits are copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_PT_Mask */ + + uint32_t ChannelStatusMask; /*!< Specifies whether the channel status and user bits are copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_ChannelStatus_Mask */ + + uint32_t ValidityBitMask; /*!< Specifies whether the validity bit is copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_V_Mask */ + + uint32_t ParityErrorMask; /*!< Specifies whether the parity error bit is copied or not into the received frame. + This parameter can be a value of @ref SPDIFRX_PE_Mask */ + +} SPDIFRX_SetDataFormatTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_SPDIFRX_STATE_RESET = 0x00U, /*!< SPDIFRX not yet initialized or disabled */ + HAL_SPDIFRX_STATE_READY = 0x01U, /*!< SPDIFRX initialized and ready for use */ + HAL_SPDIFRX_STATE_BUSY = 0x02U, /*!< SPDIFRX internal process is ongoing */ + HAL_SPDIFRX_STATE_BUSY_RX = 0x03U, /*!< SPDIFRX internal Data Flow RX process is ongoing */ + HAL_SPDIFRX_STATE_BUSY_CX = 0x04U, /*!< SPDIFRX internal Control Flow RX process is ongoing */ + HAL_SPDIFRX_STATE_ERROR = 0x07U /*!< SPDIFRX error state */ +} HAL_SPDIFRX_StateTypeDef; + +/** + * @brief SPDIFRX handle Structure definition + */ +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +typedef struct __SPDIFRX_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +{ + SPDIFRX_TypeDef *Instance; /* SPDIFRX registers base address */ + + SPDIFRX_InitTypeDef Init; /* SPDIFRX communication parameters */ + + uint32_t *pRxBuffPtr; /* Pointer to SPDIFRX Rx transfer buffer */ + + uint32_t *pCsBuffPtr; /* Pointer to SPDIFRX Cx transfer buffer */ + + __IO uint16_t RxXferSize; /* SPDIFRX Rx transfer size */ + + __IO uint16_t RxXferCount; /* SPDIFRX Rx transfer counter + (This field is initialized at the + same value as transfer size at the + beginning of the transfer and + decremented when a sample is received. + NbSamplesReceived = RxBufferSize-RxBufferCount) */ + + __IO uint16_t CsXferSize; /* SPDIFRX Rx transfer size */ + + __IO uint16_t CsXferCount; /* SPDIFRX Rx transfer counter + (This field is initialized at the + same value as transfer size at the + beginning of the transfer and + decremented when a sample is received. + NbSamplesReceived = RxBufferSize-RxBufferCount) */ + + DMA_HandleTypeDef *hdmaCsRx; /* SPDIFRX EC60958_channel_status and user_information DMA handle parameters */ + + DMA_HandleTypeDef *hdmaDrRx; /* SPDIFRX Rx DMA handle parameters */ + + __IO HAL_LockTypeDef Lock; /* SPDIFRX locking object */ + + __IO HAL_SPDIFRX_StateTypeDef State; /* SPDIFRX communication state */ + + __IO uint32_t ErrorCode; /* SPDIFRX Error code */ + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + void (*RxHalfCpltCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Data flow half completed callback */ + void (*RxCpltCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Data flow completed callback */ + void (*CxHalfCpltCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Control flow half completed callback */ + void (*CxCpltCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Control flow completed callback */ + void (*ErrorCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX error callback */ + void (* MspInitCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Msp Init callback */ + void (* MspDeInitCallback)(struct __SPDIFRX_HandleTypeDef *hspdif); /*!< SPDIFRX Msp DeInit callback */ +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + +} SPDIFRX_HandleTypeDef; +/** + * @} + */ + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +/** + * @brief HAL SPDIFRX Callback ID enumeration definition + */ +typedef enum +{ + HAL_SPDIFRX_RX_HALF_CB_ID = 0x00U, /*!< SPDIFRX Data flow half completed callback ID */ + HAL_SPDIFRX_RX_CPLT_CB_ID = 0x01U, /*!< SPDIFRX Data flow completed callback */ + HAL_SPDIFRX_CX_HALF_CB_ID = 0x02U, /*!< SPDIFRX Control flow half completed callback */ + HAL_SPDIFRX_CX_CPLT_CB_ID = 0x03U, /*!< SPDIFRX Control flow completed callback */ + HAL_SPDIFRX_ERROR_CB_ID = 0x04U, /*!< SPDIFRX error callback */ + HAL_SPDIFRX_MSPINIT_CB_ID = 0x05U, /*!< SPDIFRX Msp Init callback ID */ + HAL_SPDIFRX_MSPDEINIT_CB_ID = 0x06U /*!< SPDIFRX Msp DeInit callback ID */ +} HAL_SPDIFRX_CallbackIDTypeDef; + +/** + * @brief HAL SPDIFRX Callback pointer definition + */ +typedef void (*pSPDIFRX_CallbackTypeDef)(SPDIFRX_HandleTypeDef *hspdif); /*!< pointer to an SPDIFRX callback function */ +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPDIFRX_Exported_Constants SPDIFRX Exported Constants + * @{ + */ +/** @defgroup SPDIFRX_ErrorCode SPDIFRX Error Code + * @{ + */ +#define HAL_SPDIFRX_ERROR_NONE ((uint32_t)0x00000000U) /*!< No error */ +#define HAL_SPDIFRX_ERROR_TIMEOUT ((uint32_t)0x00000001U) /*!< Timeout error */ +#define HAL_SPDIFRX_ERROR_OVR ((uint32_t)0x00000002U) /*!< OVR error */ +#define HAL_SPDIFRX_ERROR_PE ((uint32_t)0x00000004U) /*!< Parity error */ +#define HAL_SPDIFRX_ERROR_DMA ((uint32_t)0x00000008U) /*!< DMA transfer error */ +#define HAL_SPDIFRX_ERROR_UNKNOWN ((uint32_t)0x00000010U) /*!< Unknown Error error */ +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +#define HAL_SPDIFRX_ERROR_INVALID_CALLBACK ((uint32_t)0x00000020U) /*!< Invalid Callback error */ +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SPDIFRX_Input_Selection SPDIFRX Input Selection + * @{ + */ +#define SPDIFRX_INPUT_IN0 ((uint32_t)0x00000000U) +#define SPDIFRX_INPUT_IN1 ((uint32_t)0x00010000U) +#define SPDIFRX_INPUT_IN2 ((uint32_t)0x00020000U) +#define SPDIFRX_INPUT_IN3 ((uint32_t)0x00030000U) +/** + * @} + */ + +/** @defgroup SPDIFRX_Max_Retries SPDIFRX Maximum Retries + * @{ + */ +#define SPDIFRX_MAXRETRIES_NONE ((uint32_t)0x00000000U) +#define SPDIFRX_MAXRETRIES_3 ((uint32_t)0x00001000U) +#define SPDIFRX_MAXRETRIES_15 ((uint32_t)0x00002000U) +#define SPDIFRX_MAXRETRIES_63 ((uint32_t)0x00003000U) +/** + * @} + */ + +/** @defgroup SPDIFRX_Wait_For_Activity SPDIFRX Wait For Activity + * @{ + */ +#define SPDIFRX_WAITFORACTIVITY_OFF ((uint32_t)0x00000000U) +#define SPDIFRX_WAITFORACTIVITY_ON ((uint32_t)SPDIFRX_CR_WFA) +/** + * @} + */ + +/** @defgroup SPDIFRX_PT_Mask SPDIFRX Preamble Type Mask + * @{ + */ +#define SPDIFRX_PREAMBLETYPEMASK_OFF ((uint32_t)0x00000000U) +#define SPDIFRX_PREAMBLETYPEMASK_ON ((uint32_t)SPDIFRX_CR_PTMSK) +/** + * @} + */ + +/** @defgroup SPDIFRX_ChannelStatus_Mask SPDIFRX Channel Status Mask + * @{ + */ +#define SPDIFRX_CHANNELSTATUS_OFF ((uint32_t)0x00000000U) /* The channel status and user bits are copied into the SPDIF_DR */ +#define SPDIFRX_CHANNELSTATUS_ON ((uint32_t)SPDIFRX_CR_CUMSK) /* The channel status and user bits are not copied into the SPDIF_DR, zeros are written instead*/ +/** + * @} + */ + +/** @defgroup SPDIFRX_V_Mask SPDIFRX Validity Mask + * @{ + */ +#define SPDIFRX_VALIDITYMASK_OFF ((uint32_t)0x00000000U) +#define SPDIFRX_VALIDITYMASK_ON ((uint32_t)SPDIFRX_CR_VMSK) +/** + * @} + */ + +/** @defgroup SPDIFRX_PE_Mask SPDIFRX Parity Error Mask + * @{ + */ +#define SPDIFRX_PARITYERRORMASK_OFF ((uint32_t)0x00000000U) +#define SPDIFRX_PARITYERRORMASK_ON ((uint32_t)SPDIFRX_CR_PMSK) +/** + * @} + */ + +/** @defgroup SPDIFRX_Channel_Selection SPDIFRX Channel Selection + * @{ + */ +#define SPDIFRX_CHANNEL_A ((uint32_t)0x00000000U) +#define SPDIFRX_CHANNEL_B ((uint32_t)SPDIFRX_CR_CHSEL) +/** + * @} + */ + +/** @defgroup SPDIFRX_Data_Format SPDIFRX Data Format + * @{ + */ +#define SPDIFRX_DATAFORMAT_LSB ((uint32_t)0x00000000U) +#define SPDIFRX_DATAFORMAT_MSB ((uint32_t)0x00000010U) +#define SPDIFRX_DATAFORMAT_32BITS ((uint32_t)0x00000020U) +/** + * @} + */ + +/** @defgroup SPDIFRX_Stereo_Mode SPDIFRX Stereo Mode + * @{ + */ +#define SPDIFRX_STEREOMODE_DISABLE ((uint32_t)0x00000000U) +#define SPDIFRX_STEREOMODE_ENABLE ((uint32_t)SPDIFRX_CR_RXSTEO) +/** + * @} + */ + +/** @defgroup SPDIFRX_State SPDIFRX State + * @{ + */ + +#define SPDIFRX_STATE_IDLE ((uint32_t)0xFFFFFFFCU) +#define SPDIFRX_STATE_SYNC ((uint32_t)0x00000001U) +#define SPDIFRX_STATE_RCV ((uint32_t)SPDIFRX_CR_SPDIFEN) +/** + * @} + */ + +/** @defgroup SPDIFRX_Interrupts_Definition SPDIFRX Interrupts Definition + * @{ + */ +#define SPDIFRX_IT_RXNE ((uint32_t)SPDIFRX_IMR_RXNEIE) +#define SPDIFRX_IT_CSRNE ((uint32_t)SPDIFRX_IMR_CSRNEIE) +#define SPDIFRX_IT_PERRIE ((uint32_t)SPDIFRX_IMR_PERRIE) +#define SPDIFRX_IT_OVRIE ((uint32_t)SPDIFRX_IMR_OVRIE) +#define SPDIFRX_IT_SBLKIE ((uint32_t)SPDIFRX_IMR_SBLKIE) +#define SPDIFRX_IT_SYNCDIE ((uint32_t)SPDIFRX_IMR_SYNCDIE) +#define SPDIFRX_IT_IFEIE ((uint32_t)SPDIFRX_IMR_IFEIE ) +/** + * @} + */ + +/** @defgroup SPDIFRX_Flags_Definition SPDIFRX Flags Definition + * @{ + */ +#define SPDIFRX_FLAG_RXNE ((uint32_t)SPDIFRX_SR_RXNE) +#define SPDIFRX_FLAG_CSRNE ((uint32_t)SPDIFRX_SR_CSRNE) +#define SPDIFRX_FLAG_PERR ((uint32_t)SPDIFRX_SR_PERR) +#define SPDIFRX_FLAG_OVR ((uint32_t)SPDIFRX_SR_OVR) +#define SPDIFRX_FLAG_SBD ((uint32_t)SPDIFRX_SR_SBD) +#define SPDIFRX_FLAG_SYNCD ((uint32_t)SPDIFRX_SR_SYNCD) +#define SPDIFRX_FLAG_FERR ((uint32_t)SPDIFRX_SR_FERR) +#define SPDIFRX_FLAG_SERR ((uint32_t)SPDIFRX_SR_SERR) +#define SPDIFRX_FLAG_TERR ((uint32_t)SPDIFRX_SR_TERR) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup SPDIFRX_Exported_macros SPDIFRX Exported Macros + * @{ + */ + +/** @brief Reset SPDIFRX handle state + * @param __HANDLE__ SPDIFRX handle. + * @retval None + */ +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +#define __HAL_SPDIFRX_RESET_HANDLE_STATE(__HANDLE__) do{\ + (__HANDLE__)->State = HAL_SPDIFRX_STATE_RESET;\ + (__HANDLE__)->MspInitCallback = NULL;\ + (__HANDLE__)->MspDeInitCallback = NULL;\ + }while(0) +#else +#define __HAL_SPDIFRX_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPDIFRX_STATE_RESET) +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + +/** @brief Disable the specified SPDIFRX peripheral (IDLE State). + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @retval None + */ +#define __HAL_SPDIFRX_IDLE(__HANDLE__) ((__HANDLE__)->Instance->CR &= SPDIFRX_STATE_IDLE) + +/** @brief Enable the specified SPDIFRX peripheral (SYNC State). + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @retval None + */ +#define __HAL_SPDIFRX_SYNC(__HANDLE__) ((__HANDLE__)->Instance->CR |= SPDIFRX_STATE_SYNC) + + +/** @brief Enable the specified SPDIFRX peripheral (RCV State). + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @retval None + */ +#define __HAL_SPDIFRX_RCV(__HANDLE__) ((__HANDLE__)->Instance->CR |= SPDIFRX_STATE_RCV) + + +/** @brief Enable or disable the specified SPDIFRX interrupts. + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @param __INTERRUPT__ specifies the interrupt source to enable or disable. + * This parameter can be one of the following values: + * @arg SPDIFRX_IT_RXNE + * @arg SPDIFRX_IT_CSRNE + * @arg SPDIFRX_IT_PERRIE + * @arg SPDIFRX_IT_OVRIE + * @arg SPDIFRX_IT_SBLKIE + * @arg SPDIFRX_IT_SYNCDIE + * @arg SPDIFRX_IT_IFEIE + * @retval None + */ +#define __HAL_SPDIFRX_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IMR |= (__INTERRUPT__)) +#define __HAL_SPDIFRX_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->IMR\ + &= (uint16_t)(~(__INTERRUPT__))) + +/** @brief Checks if the specified SPDIFRX interrupt source is enabled or disabled. + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @param __INTERRUPT__ specifies the SPDIFRX interrupt source to check. + * This parameter can be one of the following values: + * @arg SPDIFRX_IT_RXNE + * @arg SPDIFRX_IT_CSRNE + * @arg SPDIFRX_IT_PERRIE + * @arg SPDIFRX_IT_OVRIE + * @arg SPDIFRX_IT_SBLKIE + * @arg SPDIFRX_IT_SYNCDIE + * @arg SPDIFRX_IT_IFEIE + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_SPDIFRX_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->IMR\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks whether the specified SPDIFRX flag is set or not. + * @param __HANDLE__ specifies the SPDIFRX Handle. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SPDIFRX_FLAG_RXNE + * @arg SPDIFRX_FLAG_CSRNE + * @arg SPDIFRX_FLAG_PERR + * @arg SPDIFRX_FLAG_OVR + * @arg SPDIFRX_FLAG_SBD + * @arg SPDIFRX_FLAG_SYNCD + * @arg SPDIFRX_FLAG_FERR + * @arg SPDIFRX_FLAG_SERR + * @arg SPDIFRX_FLAG_TERR + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SPDIFRX_GET_FLAG(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->SR)\ + & (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +/** @brief Clears the specified SPDIFRX SR flag, in setting the proper IFCR register bit. + * @param __HANDLE__ specifies the USART Handle. + * @param __IT_CLEAR__ specifies the interrupt clear register flag that needs to be set + * to clear the corresponding interrupt + * This parameter can be one of the following values: + * @arg SPDIFRX_FLAG_PERR + * @arg SPDIFRX_FLAG_OVR + * @arg SPDIFRX_SR_SBD + * @arg SPDIFRX_SR_SYNCD + * @retval None + */ +#define __HAL_SPDIFRX_CLEAR_IT(__HANDLE__, __IT_CLEAR__) ((__HANDLE__)->Instance->IFCR = (uint32_t)(__IT_CLEAR__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPDIFRX_Exported_Functions + * @{ + */ + +/** @addtogroup SPDIFRX_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_SPDIFRX_Init(SPDIFRX_HandleTypeDef *hspdif); +HAL_StatusTypeDef HAL_SPDIFRX_DeInit(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_MspDeInit(SPDIFRX_HandleTypeDef *hspdif); +HAL_StatusTypeDef HAL_SPDIFRX_SetDataFormat(SPDIFRX_HandleTypeDef *hspdif, SPDIFRX_SetDataFormatTypeDef sDataFormat); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_SPDIFRX_RegisterCallback(SPDIFRX_HandleTypeDef *hspdif, HAL_SPDIFRX_CallbackIDTypeDef CallbackID, + pSPDIFRX_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SPDIFRX_UnRegisterCallback(SPDIFRX_HandleTypeDef *hspdif, + HAL_SPDIFRX_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup SPDIFRX_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ***************************************************/ +/* Blocking mode: Polling */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, + uint32_t Timeout); +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, + uint32_t Timeout); + +/* Non-Blocking mode: Interrupt */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size); +void HAL_SPDIFRX_IRQHandler(SPDIFRX_HandleTypeDef *hspdif); + +/* Non-Blocking mode: DMA */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPDIFRX_DMAStop(SPDIFRX_HandleTypeDef *hspdif); + +/* Callbacks used in non blocking modes (Interrupt and DMA) *******************/ +void HAL_SPDIFRX_RxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_ErrorCallback(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_CxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif); +void HAL_SPDIFRX_CxCpltCallback(SPDIFRX_HandleTypeDef *hspdif); +/** + * @} + */ + +/** @addtogroup SPDIFRX_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control and State functions ************************************/ +HAL_SPDIFRX_StateTypeDef HAL_SPDIFRX_GetState(SPDIFRX_HandleTypeDef const *const hspdif); +uint32_t HAL_SPDIFRX_GetError(SPDIFRX_HandleTypeDef const *const hspdif); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPDIFRX_Private_Macros SPDIFRX Private Macros + * @{ + */ +#define IS_SPDIFRX_INPUT_SELECT(INPUT) (((INPUT) == SPDIFRX_INPUT_IN1) || \ + ((INPUT) == SPDIFRX_INPUT_IN2) || \ + ((INPUT) == SPDIFRX_INPUT_IN3) || \ + ((INPUT) == SPDIFRX_INPUT_IN0)) + +#define IS_SPDIFRX_MAX_RETRIES(RET) (((RET) == SPDIFRX_MAXRETRIES_NONE) || \ + ((RET) == SPDIFRX_MAXRETRIES_3) || \ + ((RET) == SPDIFRX_MAXRETRIES_15) || \ + ((RET) == SPDIFRX_MAXRETRIES_63)) + +#define IS_SPDIFRX_WAIT_FOR_ACTIVITY(VAL) (((VAL) == SPDIFRX_WAITFORACTIVITY_ON) || \ + ((VAL) == SPDIFRX_WAITFORACTIVITY_OFF)) + +#define IS_PREAMBLE_TYPE_MASK(VAL) (((VAL) == SPDIFRX_PREAMBLETYPEMASK_ON) || \ + ((VAL) == SPDIFRX_PREAMBLETYPEMASK_OFF)) + +#define IS_VALIDITY_MASK(VAL) (((VAL) == SPDIFRX_VALIDITYMASK_OFF) || \ + ((VAL) == SPDIFRX_VALIDITYMASK_ON)) + +#define IS_PARITY_ERROR_MASK(VAL) (((VAL) == SPDIFRX_PARITYERRORMASK_OFF) || \ + ((VAL) == SPDIFRX_PARITYERRORMASK_ON)) + +#define IS_SPDIFRX_CHANNEL(CHANNEL) (((CHANNEL) == SPDIFRX_CHANNEL_A) || \ + ((CHANNEL) == SPDIFRX_CHANNEL_B)) + +#define IS_SPDIFRX_DATA_FORMAT(FORMAT) (((FORMAT) == SPDIFRX_DATAFORMAT_LSB) || \ + ((FORMAT) == SPDIFRX_DATAFORMAT_MSB) || \ + ((FORMAT) == SPDIFRX_DATAFORMAT_32BITS)) + +#define IS_STEREO_MODE(MODE) (((MODE) == SPDIFRX_STEREOMODE_DISABLE) || \ + ((MODE) == SPDIFRX_STEREOMODE_ENABLE)) + +#define IS_CHANNEL_STATUS_MASK(VAL) (((VAL) == SPDIFRX_CHANNELSTATUS_ON) || \ + ((VAL) == SPDIFRX_CHANNELSTATUS_OFF)) + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SPDIFRX_Private_Functions SPDIFRX Private Functions + * @{ + */ +/** + * @} + */ + +/** + * @} + */ +#endif /* SPDIFRX */ +/** + * @} + */ +#endif /* STM32F446xx */ + +#ifdef __cplusplus +} +#endif + + +#endif /* STM32F4xx_HAL_SPDIFRX_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h new file mode 100644 index 0000000..d7997a3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_spi.h @@ -0,0 +1,729 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_spi.h + * @author MCD Application Team + * @brief Header file of SPI 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 STM32F4xx_HAL_SPI_H +#define STM32F4xx_HAL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SPI + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SPI_Exported_Types SPI Exported Types + * @{ + */ + +/** + * @brief SPI Configuration Structure definition + */ +typedef struct +{ + uint32_t Mode; /*!< Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_Mode */ + + uint32_t Direction; /*!< Specifies the SPI bidirectional mode state. + This parameter can be a value of @ref SPI_Direction */ + + uint32_t DataSize; /*!< Specifies the SPI data size. + This parameter can be a value of @ref SPI_Data_Size */ + + uint32_t CLKPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint32_t CLKPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint32_t BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint32_t FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint32_t TIMode; /*!< Specifies if the TI mode is enabled or not. + This parameter can be a value of @ref SPI_TI_mode */ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_CRC_Calculation */ + + uint32_t CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be an odd number between Min_Data = 1 and Max_Data = 65535 */ +} SPI_InitTypeDef; + +/** + * @brief HAL SPI State structure definition + */ +typedef enum +{ + HAL_SPI_STATE_RESET = 0x00U, /*!< Peripheral not Initialized */ + HAL_SPI_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_SPI_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ + HAL_SPI_STATE_BUSY_TX = 0x03U, /*!< Data Transmission process is ongoing */ + HAL_SPI_STATE_BUSY_RX = 0x04U, /*!< Data Reception process is ongoing */ + HAL_SPI_STATE_BUSY_TX_RX = 0x05U, /*!< Data Transmission and Reception process is ongoing */ + HAL_SPI_STATE_ERROR = 0x06U, /*!< SPI error state */ + HAL_SPI_STATE_ABORT = 0x07U /*!< SPI abort is ongoing */ +} HAL_SPI_StateTypeDef; + +/** + * @brief SPI handle Structure definition + */ +typedef struct __SPI_HandleTypeDef +{ + SPI_TypeDef *Instance; /*!< SPI registers base address */ + + SPI_InitTypeDef Init; /*!< SPI communication parameters */ + + uint8_t *pTxBuffPtr; /*!< Pointer to SPI Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< SPI Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< SPI Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to SPI Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< SPI Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< SPI Rx Transfer Counter */ + + void (*RxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Rx ISR */ + + void (*TxISR)(struct __SPI_HandleTypeDef *hspi); /*!< function pointer on Tx ISR */ + + DMA_HandleTypeDef *hdmatx; /*!< SPI Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< SPI Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_SPI_StateTypeDef State; /*!< SPI communication state */ + + __IO uint32_t ErrorCode; /*!< SPI Error code */ + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + void (* TxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Completed callback */ + void (* RxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Completed callback */ + void (* TxRxCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Completed callback */ + void (* TxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Tx Half Completed callback */ + void (* RxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Rx Half Completed callback */ + void (* TxRxHalfCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI TxRx Half Completed callback */ + void (* ErrorCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Error callback */ + void (* AbortCpltCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Abort callback */ + void (* MspInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp Init callback */ + void (* MspDeInitCallback)(struct __SPI_HandleTypeDef *hspi); /*!< SPI Msp DeInit callback */ + +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} SPI_HandleTypeDef; + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +/** + * @brief HAL SPI Callback ID enumeration definition + */ +typedef enum +{ + HAL_SPI_TX_COMPLETE_CB_ID = 0x00U, /*!< SPI Tx Completed callback ID */ + HAL_SPI_RX_COMPLETE_CB_ID = 0x01U, /*!< SPI Rx Completed callback ID */ + HAL_SPI_TX_RX_COMPLETE_CB_ID = 0x02U, /*!< SPI TxRx Completed callback ID */ + HAL_SPI_TX_HALF_COMPLETE_CB_ID = 0x03U, /*!< SPI Tx Half Completed callback ID */ + HAL_SPI_RX_HALF_COMPLETE_CB_ID = 0x04U, /*!< SPI Rx Half Completed callback ID */ + HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID = 0x05U, /*!< SPI TxRx Half Completed callback ID */ + HAL_SPI_ERROR_CB_ID = 0x06U, /*!< SPI Error callback ID */ + HAL_SPI_ABORT_CB_ID = 0x07U, /*!< SPI Abort callback ID */ + HAL_SPI_MSPINIT_CB_ID = 0x08U, /*!< SPI Msp Init callback ID */ + HAL_SPI_MSPDEINIT_CB_ID = 0x09U /*!< SPI Msp DeInit callback ID */ + +} HAL_SPI_CallbackIDTypeDef; + +/** + * @brief HAL SPI Callback pointer definition + */ +typedef void (*pSPI_CallbackTypeDef)(SPI_HandleTypeDef *hspi); /*!< pointer to an SPI callback function */ + +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_Error_Code SPI Error Code + * @{ + */ +#define HAL_SPI_ERROR_NONE (0x00000000U) /*!< No error */ +#define HAL_SPI_ERROR_MODF (0x00000001U) /*!< MODF error */ +#define HAL_SPI_ERROR_CRC (0x00000002U) /*!< CRC error */ +#define HAL_SPI_ERROR_OVR (0x00000004U) /*!< OVR error */ +#define HAL_SPI_ERROR_FRE (0x00000008U) /*!< FRE error */ +#define HAL_SPI_ERROR_DMA (0x00000010U) /*!< DMA transfer error */ +#define HAL_SPI_ERROR_FLAG (0x00000020U) /*!< Error on RXNE/TXE/BSY Flag */ +#define HAL_SPI_ERROR_ABORT (0x00000040U) /*!< Error during SPI Abort procedure */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +#define HAL_SPI_ERROR_INVALID_CALLBACK (0x00000080U) /*!< Invalid Callback error */ +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SPI_Mode SPI Mode + * @{ + */ +#define SPI_MODE_SLAVE (0x00000000U) +#define SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) +/** + * @} + */ + +/** @defgroup SPI_Direction SPI Direction Mode + * @{ + */ +#define SPI_DIRECTION_2LINES (0x00000000U) +#define SPI_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY +#define SPI_DIRECTION_1LINE SPI_CR1_BIDIMODE +/** + * @} + */ + +/** @defgroup SPI_Data_Size SPI Data Size + * @{ + */ +#define SPI_DATASIZE_8BIT (0x00000000U) +#define SPI_DATASIZE_16BIT SPI_CR1_DFF +/** + * @} + */ + +/** @defgroup SPI_Clock_Polarity SPI Clock Polarity + * @{ + */ +#define SPI_POLARITY_LOW (0x00000000U) +#define SPI_POLARITY_HIGH SPI_CR1_CPOL +/** + * @} + */ + +/** @defgroup SPI_Clock_Phase SPI Clock Phase + * @{ + */ +#define SPI_PHASE_1EDGE (0x00000000U) +#define SPI_PHASE_2EDGE SPI_CR1_CPHA +/** + * @} + */ + +/** @defgroup SPI_Slave_Select_management SPI Slave Select Management + * @{ + */ +#define SPI_NSS_SOFT SPI_CR1_SSM +#define SPI_NSS_HARD_INPUT (0x00000000U) +#define SPI_NSS_HARD_OUTPUT (SPI_CR2_SSOE << 16U) +/** + * @} + */ + +/** @defgroup SPI_BaudRate_Prescaler SPI BaudRate Prescaler + * @{ + */ +#define SPI_BAUDRATEPRESCALER_2 (0x00000000U) +#define SPI_BAUDRATEPRESCALER_4 (SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_8 (SPI_CR1_BR_1) +#define SPI_BAUDRATEPRESCALER_16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_32 (SPI_CR1_BR_2) +#define SPI_BAUDRATEPRESCALER_64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) +#define SPI_BAUDRATEPRESCALER_128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) +#define SPI_BAUDRATEPRESCALER_256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) +/** + * @} + */ + +/** @defgroup SPI_MSB_LSB_transmission SPI MSB LSB Transmission + * @{ + */ +#define SPI_FIRSTBIT_MSB (0x00000000U) +#define SPI_FIRSTBIT_LSB SPI_CR1_LSBFIRST +/** + * @} + */ + +/** @defgroup SPI_TI_mode SPI TI Mode + * @{ + */ +#define SPI_TIMODE_DISABLE (0x00000000U) +#define SPI_TIMODE_ENABLE SPI_CR2_FRF +/** + * @} + */ + +/** @defgroup SPI_CRC_Calculation SPI CRC Calculation + * @{ + */ +#define SPI_CRCCALCULATION_DISABLE (0x00000000U) +#define SPI_CRCCALCULATION_ENABLE SPI_CR1_CRCEN +/** + * @} + */ + +/** @defgroup SPI_Interrupt_definition SPI Interrupt Definition + * @{ + */ +#define SPI_IT_TXE SPI_CR2_TXEIE +#define SPI_IT_RXNE SPI_CR2_RXNEIE +#define SPI_IT_ERR SPI_CR2_ERRIE +/** + * @} + */ + +/** @defgroup SPI_Flags_definition SPI Flags Definition + * @{ + */ +#define SPI_FLAG_RXNE SPI_SR_RXNE /* SPI status flag: Rx buffer not empty flag */ +#define SPI_FLAG_TXE SPI_SR_TXE /* SPI status flag: Tx buffer empty flag */ +#define SPI_FLAG_BSY SPI_SR_BSY /* SPI status flag: Busy flag */ +#define SPI_FLAG_CRCERR SPI_SR_CRCERR /* SPI Error flag: CRC error flag */ +#define SPI_FLAG_MODF SPI_SR_MODF /* SPI Error flag: Mode fault flag */ +#define SPI_FLAG_OVR SPI_SR_OVR /* SPI Error flag: Overrun flag */ +#define SPI_FLAG_FRE SPI_SR_FRE /* SPI Error flag: TI mode frame format error flag */ +#define SPI_FLAG_MASK (SPI_SR_RXNE | SPI_SR_TXE | SPI_SR_BSY | SPI_SR_CRCERR\ + | SPI_SR_MODF | SPI_SR_OVR | SPI_SR_FRE) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macros -----------------------------------------------------------*/ +/** @defgroup SPI_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @brief Reset SPI handle state. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_SPI_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SPI_STATE_RESET) +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + +/** @brief Enable the specified SPI interrupts. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the interrupt source to enable. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_SPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) + +/** @brief Disable the specified SPI interrupts. + * @param __HANDLE__ specifies the SPI handle. + * This parameter can be SPIx where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the interrupt source to disable. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval None + */ +#define __HAL_SPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR2, (__INTERRUPT__)) + +/** @brief Check whether the specified SPI interrupt source is enabled or not. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __INTERRUPT__ specifies the SPI interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_SPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->CR2\ + & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET) + +/** @brief Check whether the specified SPI flag is set or not. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SPI_FLAG_RXNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXE: Transmit buffer empty flag + * @arg SPI_FLAG_CRCERR: CRC error flag + * @arg SPI_FLAG_MODF: Mode fault flag + * @arg SPI_FLAG_OVR: Overrun flag + * @arg SPI_FLAG_BSY: Busy flag + * @arg SPI_FLAG_FRE: Frame format error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_SPI_GET_FLAG(__HANDLE__, __FLAG__) ((((__HANDLE__)->Instance->SR) & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the SPI CRCERR pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_CRCERRFLAG(__HANDLE__) ((__HANDLE__)->Instance->SR = (uint16_t)(~SPI_FLAG_CRCERR)) + +/** @brief Clear the SPI MODF pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_MODFFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg_modf = 0x00U; \ + tmpreg_modf = (__HANDLE__)->Instance->SR; \ + CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE); \ + UNUSED(tmpreg_modf); \ + } while(0U) + +/** @brief Clear the SPI OVR pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_OVRFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg_ovr = 0x00U; \ + tmpreg_ovr = (__HANDLE__)->Instance->DR; \ + tmpreg_ovr = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_ovr); \ + } while(0U) + +/** @brief Clear the SPI FRE pending flag. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_CLEAR_FREFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg_fre = 0x00U; \ + tmpreg_fre = (__HANDLE__)->Instance->SR; \ + UNUSED(tmpreg_fre); \ + }while(0U) + +/** @brief Enable the SPI peripheral. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) + +/** @brief Disable the SPI peripheral. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define __HAL_SPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_SPE) + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPI_Private_Macros SPI Private Macros + * @{ + */ + +/** @brief Set the SPI transmit-only mode. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_1LINE_TX(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) + +/** @brief Set the SPI receive-only mode. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_1LINE_RX(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_BIDIOE) + +/** @brief Reset the CRC calculation of the SPI. + * @param __HANDLE__ specifies the SPI Handle. + * This parameter can be SPI where x: 1, 2, or 3 to select the SPI peripheral. + * @retval None + */ +#define SPI_RESET_CRC(__HANDLE__) do{CLEAR_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN);\ + SET_BIT((__HANDLE__)->Instance->CR1, SPI_CR1_CRCEN);}while(0U) + +/** @brief Check whether the specified SPI flag is set or not. + * @param __SR__ copy of SPI SR register. + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg SPI_FLAG_RXNE: Receive buffer not empty flag + * @arg SPI_FLAG_TXE: Transmit buffer empty flag + * @arg SPI_FLAG_CRCERR: CRC error flag + * @arg SPI_FLAG_MODF: Mode fault flag + * @arg SPI_FLAG_OVR: Overrun flag + * @arg SPI_FLAG_BSY: Busy flag + * @arg SPI_FLAG_FRE: Frame format error flag + * @retval SET or RESET. + */ +#define SPI_CHECK_FLAG(__SR__, __FLAG__) ((((__SR__) & ((__FLAG__) & SPI_FLAG_MASK)) == \ + ((__FLAG__) & SPI_FLAG_MASK)) ? SET : RESET) + +/** @brief Check whether the specified SPI Interrupt is set or not. + * @param __CR2__ copy of SPI CR2 register. + * @param __INTERRUPT__ specifies the SPI interrupt source to check. + * This parameter can be one of the following values: + * @arg SPI_IT_TXE: Tx buffer empty interrupt enable + * @arg SPI_IT_RXNE: RX buffer not empty interrupt enable + * @arg SPI_IT_ERR: Error interrupt enable + * @retval SET or RESET. + */ +#define SPI_CHECK_IT_SOURCE(__CR2__, __INTERRUPT__) ((((__CR2__) & (__INTERRUPT__)) == \ + (__INTERRUPT__)) ? SET : RESET) + +/** @brief Checks if SPI Mode parameter is in allowed range. + * @param __MODE__ specifies the SPI Mode. + * This parameter can be a value of @ref SPI_Mode + * @retval None + */ +#define IS_SPI_MODE(__MODE__) (((__MODE__) == SPI_MODE_SLAVE) || \ + ((__MODE__) == SPI_MODE_MASTER)) + +/** @brief Checks if SPI Direction Mode parameter is in allowed range. + * @param __MODE__ specifies the SPI Direction Mode. + * This parameter can be a value of @ref SPI_Direction + * @retval None + */ +#define IS_SPI_DIRECTION(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ + ((__MODE__) == SPI_DIRECTION_2LINES_RXONLY) || \ + ((__MODE__) == SPI_DIRECTION_1LINE)) + +/** @brief Checks if SPI Direction Mode parameter is 2 lines. + * @param __MODE__ specifies the SPI Direction Mode. + * @retval None + */ +#define IS_SPI_DIRECTION_2LINES(__MODE__) ((__MODE__) == SPI_DIRECTION_2LINES) + +/** @brief Checks if SPI Direction Mode parameter is 1 or 2 lines. + * @param __MODE__ specifies the SPI Direction Mode. + * @retval None + */ +#define IS_SPI_DIRECTION_2LINES_OR_1LINE(__MODE__) (((__MODE__) == SPI_DIRECTION_2LINES) || \ + ((__MODE__) == SPI_DIRECTION_1LINE)) + +/** @brief Checks if SPI Data Size parameter is in allowed range. + * @param __DATASIZE__ specifies the SPI Data Size. + * This parameter can be a value of @ref SPI_Data_Size + * @retval None + */ +#define IS_SPI_DATASIZE(__DATASIZE__) (((__DATASIZE__) == SPI_DATASIZE_16BIT) || \ + ((__DATASIZE__) == SPI_DATASIZE_8BIT)) + +/** @brief Checks if SPI Serial clock steady state parameter is in allowed range. + * @param __CPOL__ specifies the SPI serial clock steady state. + * This parameter can be a value of @ref SPI_Clock_Polarity + * @retval None + */ +#define IS_SPI_CPOL(__CPOL__) (((__CPOL__) == SPI_POLARITY_LOW) || \ + ((__CPOL__) == SPI_POLARITY_HIGH)) + +/** @brief Checks if SPI Clock Phase parameter is in allowed range. + * @param __CPHA__ specifies the SPI Clock Phase. + * This parameter can be a value of @ref SPI_Clock_Phase + * @retval None + */ +#define IS_SPI_CPHA(__CPHA__) (((__CPHA__) == SPI_PHASE_1EDGE) || \ + ((__CPHA__) == SPI_PHASE_2EDGE)) + +/** @brief Checks if SPI Slave Select parameter is in allowed range. + * @param __NSS__ specifies the SPI Slave Select management parameter. + * This parameter can be a value of @ref SPI_Slave_Select_management + * @retval None + */ +#define IS_SPI_NSS(__NSS__) (((__NSS__) == SPI_NSS_SOFT) || \ + ((__NSS__) == SPI_NSS_HARD_INPUT) || \ + ((__NSS__) == SPI_NSS_HARD_OUTPUT)) + +/** @brief Checks if SPI Baudrate prescaler parameter is in allowed range. + * @param __PRESCALER__ specifies the SPI Baudrate prescaler. + * This parameter can be a value of @ref SPI_BaudRate_Prescaler + * @retval None + */ +#define IS_SPI_BAUDRATE_PRESCALER(__PRESCALER__) (((__PRESCALER__) == SPI_BAUDRATEPRESCALER_2) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_4) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_8) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_16) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_32) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_64) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_128) || \ + ((__PRESCALER__) == SPI_BAUDRATEPRESCALER_256)) + +/** @brief Checks if SPI MSB LSB transmission parameter is in allowed range. + * @param __BIT__ specifies the SPI MSB LSB transmission (whether data transfer starts from MSB or LSB bit). + * This parameter can be a value of @ref SPI_MSB_LSB_transmission + * @retval None + */ +#define IS_SPI_FIRST_BIT(__BIT__) (((__BIT__) == SPI_FIRSTBIT_MSB) || \ + ((__BIT__) == SPI_FIRSTBIT_LSB)) + +/** @brief Checks if SPI TI mode parameter is in allowed range. + * @param __MODE__ specifies the SPI TI mode. + * This parameter can be a value of @ref SPI_TI_mode + * @retval None + */ +#define IS_SPI_TIMODE(__MODE__) (((__MODE__) == SPI_TIMODE_DISABLE) || \ + ((__MODE__) == SPI_TIMODE_ENABLE)) + +/** @brief Checks if SPI CRC calculation enabled state is in allowed range. + * @param __CALCULATION__ specifies the SPI CRC calculation enable state. + * This parameter can be a value of @ref SPI_CRC_Calculation + * @retval None + */ +#define IS_SPI_CRC_CALCULATION(__CALCULATION__) (((__CALCULATION__) == SPI_CRCCALCULATION_DISABLE) || \ + ((__CALCULATION__) == SPI_CRCCALCULATION_ENABLE)) + +/** @brief Checks if SPI polynomial value to be used for the CRC calculation, is in allowed range. + * @param __POLYNOMIAL__ specifies the SPI polynomial value to be used for the CRC calculation. + * This parameter must be a number between Min_Data = 0 and Max_Data = 65535 + * @retval None + */ +#define IS_SPI_CRC_POLYNOMIAL(__POLYNOMIAL__) (((__POLYNOMIAL__) >= 0x1U) && \ + ((__POLYNOMIAL__) <= 0xFFFFU) && \ + (((__POLYNOMIAL__)&0x1U) != 0U)) + +/** @brief Checks if DMA handle is valid. + * @param __HANDLE__ specifies a DMA Handle. + * @retval None + */ +#define IS_SPI_DMA_HANDLE(__HANDLE__) ((__HANDLE__) != NULL) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPI_Exported_Functions + * @{ + */ + +/** @addtogroup SPI_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi); +void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi); +void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, + pSPI_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ***************************************************/ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, + uint32_t Timeout); +HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size); +HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi); +HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi); + +void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi); +void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi); +/** + * @} + */ + +/** @addtogroup SPI_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State and Error functions ***************************************/ +HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *hspi); +uint32_t HAL_SPI_GetError(SPI_HandleTypeDef *hspi); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_SPI_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h new file mode 100644 index 0000000..e135aa1 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_sram.h @@ -0,0 +1,236 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sram.h + * @author MCD Application Team + * @brief Header file of SRAM 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 STM32F4xx_HAL_SRAM_H +#define STM32F4xx_HAL_SRAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMC_Bank1) || defined(FSMC_Bank1) + +/* Includes ------------------------------------------------------------------*/ +#if defined(FSMC_Bank1) +#include "stm32f4xx_ll_fsmc.h" +#else +#include "stm32f4xx_ll_fmc.h" +#endif /* FSMC_Bank1 */ + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +/** @addtogroup SRAM + * @{ + */ + +/* Exported typedef ----------------------------------------------------------*/ + +/** @defgroup SRAM_Exported_Types SRAM Exported Types + * @{ + */ +/** + * @brief HAL SRAM State structures definition + */ +typedef enum +{ + HAL_SRAM_STATE_RESET = 0x00U, /*!< SRAM not yet initialized or disabled */ + HAL_SRAM_STATE_READY = 0x01U, /*!< SRAM initialized and ready for use */ + HAL_SRAM_STATE_BUSY = 0x02U, /*!< SRAM internal process is ongoing */ + HAL_SRAM_STATE_ERROR = 0x03U, /*!< SRAM error state */ + HAL_SRAM_STATE_PROTECTED = 0x04U /*!< SRAM peripheral NORSRAM device write protected */ + +} HAL_SRAM_StateTypeDef; + +/** + * @brief SRAM handle Structure definition + */ +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) +typedef struct __SRAM_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +{ + FMC_NORSRAM_TypeDef *Instance; /*!< Register base address */ + + FMC_NORSRAM_EXTENDED_TypeDef *Extended; /*!< Extended mode register base address */ + + FMC_NORSRAM_InitTypeDef Init; /*!< SRAM device control configuration parameters */ + + HAL_LockTypeDef Lock; /*!< SRAM locking object */ + + __IO HAL_SRAM_StateTypeDef State; /*!< SRAM device access state */ + + DMA_HandleTypeDef *hdma; /*!< Pointer DMA handler */ + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + void (* MspInitCallback)(struct __SRAM_HandleTypeDef *hsram); /*!< SRAM Msp Init callback */ + void (* MspDeInitCallback)(struct __SRAM_HandleTypeDef *hsram); /*!< SRAM Msp DeInit callback */ + void (* DmaXferCpltCallback)(DMA_HandleTypeDef *hdma); /*!< SRAM DMA Xfer Complete callback */ + void (* DmaXferErrorCallback)(DMA_HandleTypeDef *hdma); /*!< SRAM DMA Xfer Error callback */ +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +} SRAM_HandleTypeDef; + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) +/** + * @brief HAL SRAM Callback ID enumeration definition + */ +typedef enum +{ + HAL_SRAM_MSP_INIT_CB_ID = 0x00U, /*!< SRAM MspInit Callback ID */ + HAL_SRAM_MSP_DEINIT_CB_ID = 0x01U, /*!< SRAM MspDeInit Callback ID */ + HAL_SRAM_DMA_XFER_CPLT_CB_ID = 0x02U, /*!< SRAM DMA Xfer Complete Callback ID */ + HAL_SRAM_DMA_XFER_ERR_CB_ID = 0x03U /*!< SRAM DMA Xfer Complete Callback ID */ +} HAL_SRAM_CallbackIDTypeDef; + +/** + * @brief HAL SRAM Callback pointer definition + */ +typedef void (*pSRAM_CallbackTypeDef)(SRAM_HandleTypeDef *hsram); +typedef void (*pSRAM_DmaCallbackTypeDef)(DMA_HandleTypeDef *hdma); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ + +/** @defgroup SRAM_Exported_Macros SRAM Exported Macros + * @{ + */ + +/** @brief Reset SRAM handle state + * @param __HANDLE__ SRAM handle + * @retval None + */ +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) +#define __HAL_SRAM_RESET_HANDLE_STATE(__HANDLE__) do { \ + (__HANDLE__)->State = HAL_SRAM_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_SRAM_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_SRAM_STATE_RESET) +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SRAM_Exported_Functions SRAM Exported Functions + * @{ + */ + +/** @addtogroup SRAM_Exported_Functions_Group1 Initialization and de-initialization functions + * @{ + */ + +/* Initialization/de-initialization functions ********************************/ +HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram, FMC_NORSRAM_TimingTypeDef *Timing, + FMC_NORSRAM_TimingTypeDef *ExtTiming); +HAL_StatusTypeDef HAL_SRAM_DeInit(SRAM_HandleTypeDef *hsram); +void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram); +void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram); + +/** + * @} + */ + +/** @addtogroup SRAM_Exported_Functions_Group2 Input Output and memory control functions + * @{ + */ + +/* I/O operation functions ***************************************************/ +HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pSrcBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize); +HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize); + +void HAL_SRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma); +void HAL_SRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma); + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) +/* SRAM callback registering/unregistering */ +HAL_StatusTypeDef HAL_SRAM_RegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId, + pSRAM_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_SRAM_UnRegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId); +HAL_StatusTypeDef HAL_SRAM_RegisterDmaCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId, + pSRAM_DmaCallbackTypeDef pCallback); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup SRAM_Exported_Functions_Group3 Control functions + * @{ + */ + +/* SRAM Control functions ****************************************************/ +HAL_StatusTypeDef HAL_SRAM_WriteOperation_Enable(SRAM_HandleTypeDef *hsram); +HAL_StatusTypeDef HAL_SRAM_WriteOperation_Disable(SRAM_HandleTypeDef *hsram); + +/** + * @} + */ + +/** @addtogroup SRAM_Exported_Functions_Group4 Peripheral State functions + * @{ + */ + +/* SRAM State functions ******************************************************/ +HAL_SRAM_StateTypeDef HAL_SRAM_GetState(SRAM_HandleTypeDef *hsram); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank1 || FSMC_Bank1 */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_SRAM_H */ diff --git a/libs/hal/stm32f4xx_hal_tim.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h similarity index 98% rename from libs/hal/stm32f4xx_hal_tim.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h index 8c81414..3a1da9d 100644 --- a/libs/hal/stm32f4xx_hal_tim.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim.h @@ -1896,7 +1896,7 @@ HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim); HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim); HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim); /* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length); HAL_StatusTypeDef HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim); /** * @} @@ -1918,7 +1918,8 @@ HAL_StatusTypeDef HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_StatusTypeDef HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); /* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length); HAL_StatusTypeDef HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); /** * @} @@ -1940,7 +1941,8 @@ HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_StatusTypeDef HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); /* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length); HAL_StatusTypeDef HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); /** * @} @@ -2025,21 +2027,25 @@ void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim); * @{ */ /* Control functions *********************************************************/ -HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef *sConfig, uint32_t Channel); -HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef *sConfig, uint32_t Channel); -HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef *sConfig, uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig, + uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_OC_InitTypeDef *sConfig, + uint32_t Channel); +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig, + uint32_t Channel); HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OnePulse_InitTypeDef *sConfig, uint32_t OutputChannel, uint32_t InputChannel); -HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, TIM_ClearInputConfigTypeDef *sClearInputConfig, +HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, + const TIM_ClearInputConfigTypeDef *sClearInputConfig, uint32_t Channel); -HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef *sClockSourceConfig); +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig); HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_Selection); -HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef *sSlaveConfig); -HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef *sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig); +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig); HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, - uint32_t BurstRequestSrc, uint32_t *BurstBuffer, uint32_t BurstLength); + uint32_t BurstRequestSrc, const uint32_t *BurstBuffer, uint32_t BurstLength); HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, - uint32_t BurstRequestSrc, uint32_t *BurstBuffer, + uint32_t BurstRequestSrc, const uint32_t *BurstBuffer, uint32_t BurstLength, uint32_t DataLength); HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, @@ -2049,7 +2055,7 @@ HAL_StatusTypeDef HAL_TIM_DMABurst_MultiReadStart(TIM_HandleTypeDef *htim, uint3 uint32_t BurstLength, uint32_t DataLength); HAL_StatusTypeDef HAL_TIM_DMABurst_ReadStop(TIM_HandleTypeDef *htim, uint32_t BurstRequestSrc); HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventSource); -uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel); +uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel); /** * @} */ @@ -2086,17 +2092,17 @@ HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_Ca * @{ */ /* Peripheral State functions ************************************************/ -HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim); /* Peripheral Channel state functions ************************************************/ -HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(TIM_HandleTypeDef *htim); -HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(TIM_HandleTypeDef *htim, uint32_t Channel); -HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(TIM_HandleTypeDef *htim); +HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim); +HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim, uint32_t Channel); +HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim); /** * @} */ @@ -2110,9 +2116,9 @@ HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(TIM_HandleTypeDef *htim); /** @defgroup TIM_Private_Functions TIM Private Functions * @{ */ -void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure); +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure); void TIM_TI1_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter); -void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config); void TIM_ETR_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ExtTRGPrescaler, uint32_t TIM_ExtTRGPolarity, uint32_t ExtTRGFilter); diff --git a/libs/hal/stm32f4xx_hal_tim_ex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h similarity index 96% rename from libs/hal/stm32f4xx_hal_tim_ex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h index 39fb500..561e9bb 100644 --- a/libs/hal/stm32f4xx_hal_tim_ex.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_tim_ex.h @@ -74,9 +74,8 @@ typedef struct #if defined (TIM2) #if defined(TIM8) #define TIM_TIM2_TIM8_TRGO 0x00000000U /*!< TIM2 ITR1 is connected to TIM8 TRGO */ -#else -#define TIM_TIM2_ETH_PTP TIM_OR_ITR1_RMP_0 /*!< TIM2 ITR1 is connected to PTP trigger output */ #endif /* TIM8 */ +#define TIM_TIM2_ETH_PTP TIM_OR_ITR1_RMP_0 /*!< TIM2 ITR1 is connected to PTP trigger output */ #define TIM_TIM2_USBFS_SOF TIM_OR_ITR1_RMP_1 /*!< TIM2 ITR1 is connected to OTG FS SOF */ #define TIM_TIM2_USBHS_SOF (TIM_OR_ITR1_RMP_1 | TIM_OR_ITR1_RMP_0) /*!< TIM2 ITR1 is connected to OTG HS SOF */ #endif /* TIM2 */ @@ -205,7 +204,7 @@ typedef struct * @{ */ /* Timer Hall Sensor functions **********************************************/ -HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef *sConfig); +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig); HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim); void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim); @@ -238,7 +237,8 @@ HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Chann HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); /* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length); HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); /** * @} @@ -257,7 +257,8 @@ HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel); /* Non-Blocking mode: DMA */ -HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length); +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length); HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel); /** * @} @@ -291,9 +292,9 @@ HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32 HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger, uint32_t CommutationSource); HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, - TIM_MasterConfigTypeDef *sMasterConfig); + const TIM_MasterConfigTypeDef *sMasterConfig); HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, - TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig); + const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig); HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap); /** * @} @@ -316,8 +317,8 @@ void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim); * @{ */ /* Extended Peripheral State functions ***************************************/ -HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim); -HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(TIM_HandleTypeDef *htim, uint32_t ChannelN); +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim); +HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim, uint32_t ChannelN); /** * @} */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h new file mode 100644 index 0000000..e6ce82f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_uart.h @@ -0,0 +1,909 @@ +/** + ****************************************************************************** + * @file stm32f4xx_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 __STM32F4xx_HAL_UART_H +#define __STM32F4xx_HAL_UART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_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) / (8 * (OVR8+1) * (huart->Init.BaudRate))) + - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8 * (OVR8+1)) + 0.5 + Where OVR8 is the "oversampling by 8 mode" configuration bit in the CR1 register. */ + + 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 */ +} 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 +#define UART_OVERSAMPLING_8 ((uint32_t)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) + +/** @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)) + +/** @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)) +#define IS_UART_OVERSAMPLING(SAMPLING) (((SAMPLING) == UART_OVERSAMPLING_16) || \ + ((SAMPLING) == UART_OVERSAMPLING_8)) +#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) <= 10500000U) +#define IS_UART_ADDRESS(ADDRESS) ((ADDRESS) <= 0x0FU) + +#define UART_DIV_SAMPLING16(_PCLK_, _BAUD_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(4U*((uint64_t)(_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_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(2U*((uint64_t)(_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 /* __STM32F4xx_HAL_UART_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h new file mode 100644 index 0000000..e4bfcf3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_usart.h @@ -0,0 +1,648 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_usart.h + * @author MCD Application Team + * @brief Header file of USART 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 __STM32F4xx_HAL_USART_H +#define __STM32F4xx_HAL_USART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup USART + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup USART_Exported_Types USART Exported Types + * @{ + */ + +/** + * @brief USART Init Structure definition + */ +typedef struct +{ + uint32_t BaudRate; /*!< This member configures the Usart communication baud rate. + The baud rate is computed using the following formula: + - IntegerDivider = ((PCLKx) / (8 * (husart->Init.BaudRate))) + - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 8) + 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 USART_Word_Length */ + + uint32_t StopBits; /*!< Specifies the number of stop bits transmitted. + This parameter can be a value of @ref USART_Stop_Bits */ + + uint32_t Parity; /*!< Specifies the parity mode. + This parameter can be a value of @ref USART_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 USART_Mode */ + + uint32_t CLKPolarity; /*!< Specifies the steady state of the serial clock. + This parameter can be a value of @ref USART_Clock_Polarity */ + + uint32_t CLKPhase; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref USART_Clock_Phase */ + + uint32_t CLKLastBit; /*!< 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_Last_Bit */ +} USART_InitTypeDef; + +/** + * @brief HAL State structures definition + */ +typedef enum +{ + HAL_USART_STATE_RESET = 0x00U, /*!< Peripheral is not yet Initialized */ + HAL_USART_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_USART_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ + HAL_USART_STATE_BUSY_TX = 0x12U, /*!< Data Transmission process is ongoing */ + HAL_USART_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_USART_STATE_BUSY_TX_RX = 0x32U, /*!< Data Transmission Reception process is ongoing */ + HAL_USART_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ + HAL_USART_STATE_ERROR = 0x04U /*!< Error */ +} HAL_USART_StateTypeDef; + +/** + * @brief USART handle Structure definition + */ +typedef struct __USART_HandleTypeDef +{ + USART_TypeDef *Instance; /*!< USART registers base address */ + + USART_InitTypeDef Init; /*!< Usart communication parameters */ + + const uint8_t *pTxBuffPtr; /*!< Pointer to Usart Tx transfer Buffer */ + + uint16_t TxXferSize; /*!< Usart Tx Transfer size */ + + __IO uint16_t TxXferCount; /*!< Usart Tx Transfer Counter */ + + uint8_t *pRxBuffPtr; /*!< Pointer to Usart Rx transfer Buffer */ + + uint16_t RxXferSize; /*!< Usart Rx Transfer size */ + + __IO uint16_t RxXferCount; /*!< Usart Rx Transfer Counter */ + + DMA_HandleTypeDef *hdmatx; /*!< Usart Tx DMA Handle parameters */ + + DMA_HandleTypeDef *hdmarx; /*!< Usart Rx DMA Handle parameters */ + + HAL_LockTypeDef Lock; /*!< Locking object */ + + __IO HAL_USART_StateTypeDef State; /*!< Usart communication state */ + + __IO uint32_t ErrorCode; /*!< USART Error code */ + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + void (* TxHalfCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Tx Half Complete Callback */ + void (* TxCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Tx Complete Callback */ + void (* RxHalfCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Rx Half Complete Callback */ + void (* RxCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Rx Complete Callback */ + void (* TxRxCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Tx Rx Complete Callback */ + void (* ErrorCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Error Callback */ + void (* AbortCpltCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Abort Complete Callback */ + + void (* MspInitCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Msp Init callback */ + void (* MspDeInitCallback)(struct __USART_HandleTypeDef *husart); /*!< USART Msp DeInit callback */ +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +} USART_HandleTypeDef; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +/** + * @brief HAL USART Callback ID enumeration definition + */ +typedef enum +{ + HAL_USART_TX_HALFCOMPLETE_CB_ID = 0x00U, /*!< USART Tx Half Complete Callback ID */ + HAL_USART_TX_COMPLETE_CB_ID = 0x01U, /*!< USART Tx Complete Callback ID */ + HAL_USART_RX_HALFCOMPLETE_CB_ID = 0x02U, /*!< USART Rx Half Complete Callback ID */ + HAL_USART_RX_COMPLETE_CB_ID = 0x03U, /*!< USART Rx Complete Callback ID */ + HAL_USART_TX_RX_COMPLETE_CB_ID = 0x04U, /*!< USART Tx Rx Complete Callback ID */ + HAL_USART_ERROR_CB_ID = 0x05U, /*!< USART Error Callback ID */ + HAL_USART_ABORT_COMPLETE_CB_ID = 0x06U, /*!< USART Abort Complete Callback ID */ + + HAL_USART_MSPINIT_CB_ID = 0x07U, /*!< USART MspInit callback ID */ + HAL_USART_MSPDEINIT_CB_ID = 0x08U /*!< USART MspDeInit callback ID */ + +} HAL_USART_CallbackIDTypeDef; + +/** + * @brief HAL USART Callback pointer definition + */ +typedef void (*pUSART_CallbackTypeDef)(USART_HandleTypeDef *husart); /*!< pointer to an USART callback function */ + +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup USART_Exported_Constants USART Exported Constants + * @{ + */ + +/** @defgroup USART_Error_Code USART Error Code + * @brief USART Error Code + * @{ + */ +#define HAL_USART_ERROR_NONE 0x00000000U /*!< No error */ +#define HAL_USART_ERROR_PE 0x00000001U /*!< Parity error */ +#define HAL_USART_ERROR_NE 0x00000002U /*!< Noise error */ +#define HAL_USART_ERROR_FE 0x00000004U /*!< Frame error */ +#define HAL_USART_ERROR_ORE 0x00000008U /*!< Overrun error */ +#define HAL_USART_ERROR_DMA 0x00000010U /*!< DMA transfer error */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +#define HAL_USART_ERROR_INVALID_CALLBACK 0x00000020U /*!< Invalid Callback error */ +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup USART_Word_Length USART Word Length + * @{ + */ +#define USART_WORDLENGTH_8B 0x00000000U +#define USART_WORDLENGTH_9B ((uint32_t)USART_CR1_M) +/** + * @} + */ + +/** @defgroup USART_Stop_Bits USART Number of Stop Bits + * @{ + */ +#define USART_STOPBITS_1 0x00000000U +#define USART_STOPBITS_0_5 ((uint32_t)USART_CR2_STOP_0) +#define USART_STOPBITS_2 ((uint32_t)USART_CR2_STOP_1) +#define USART_STOPBITS_1_5 ((uint32_t)(USART_CR2_STOP_0 | USART_CR2_STOP_1)) +/** + * @} + */ + +/** @defgroup USART_Parity USART Parity + * @{ + */ +#define USART_PARITY_NONE 0x00000000U +#define USART_PARITY_EVEN ((uint32_t)USART_CR1_PCE) +#define USART_PARITY_ODD ((uint32_t)(USART_CR1_PCE | USART_CR1_PS)) +/** + * @} + */ + +/** @defgroup USART_Mode USART Mode + * @{ + */ +#define USART_MODE_RX ((uint32_t)USART_CR1_RE) +#define USART_MODE_TX ((uint32_t)USART_CR1_TE) +#define USART_MODE_TX_RX ((uint32_t)(USART_CR1_TE | USART_CR1_RE)) +/** + * @} + */ + +/** @defgroup USART_Clock USART Clock + * @{ + */ +#define USART_CLOCK_DISABLE 0x00000000U +#define USART_CLOCK_ENABLE ((uint32_t)USART_CR2_CLKEN) +/** + * @} + */ + +/** @defgroup USART_Clock_Polarity USART Clock Polarity + * @{ + */ +#define USART_POLARITY_LOW 0x00000000U +#define USART_POLARITY_HIGH ((uint32_t)USART_CR2_CPOL) +/** + * @} + */ + +/** @defgroup USART_Clock_Phase USART Clock Phase + * @{ + */ +#define USART_PHASE_1EDGE 0x00000000U +#define USART_PHASE_2EDGE ((uint32_t)USART_CR2_CPHA) +/** + * @} + */ + +/** @defgroup USART_Last_Bit USART Last Bit + * @{ + */ +#define USART_LASTBIT_DISABLE 0x00000000U +#define USART_LASTBIT_ENABLE ((uint32_t)USART_CR2_LBCL) +/** + * @} + */ + +/** @defgroup USART_NACK_State USART NACK State + * @{ + */ +#define USART_NACK_ENABLE ((uint32_t)USART_CR3_NACK) +#define USART_NACK_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup USART_Flags USART Flags + * Elements values convention: 0xXXXX + * - 0xXXXX : Flag mask in the SR register + * @{ + */ +#define USART_FLAG_TXE ((uint32_t)USART_SR_TXE) +#define USART_FLAG_TC ((uint32_t)USART_SR_TC) +#define USART_FLAG_RXNE ((uint32_t)USART_SR_RXNE) +#define USART_FLAG_IDLE ((uint32_t)USART_SR_IDLE) +#define USART_FLAG_ORE ((uint32_t)USART_SR_ORE) +#define USART_FLAG_NE ((uint32_t)USART_SR_NE) +#define USART_FLAG_FE ((uint32_t)USART_SR_FE) +#define USART_FLAG_PE ((uint32_t)USART_SR_PE) +/** + * @} + */ + +/** @defgroup USART_Interrupt_definition USART Interrupts Definition + * Elements values convention: 0xY000XXXX + * - XXXX : Interrupt mask in the XX register + * - Y : Interrupt source register (2bits) + * - 01: CR1 register + * - 10: CR2 register + * - 11: CR3 register + * @{ + */ +#define USART_IT_PE ((uint32_t)(USART_CR1_REG_INDEX << 28U | USART_CR1_PEIE)) +#define USART_IT_TXE ((uint32_t)(USART_CR1_REG_INDEX << 28U | USART_CR1_TXEIE)) +#define USART_IT_TC ((uint32_t)(USART_CR1_REG_INDEX << 28U | USART_CR1_TCIE)) +#define USART_IT_RXNE ((uint32_t)(USART_CR1_REG_INDEX << 28U | USART_CR1_RXNEIE)) +#define USART_IT_IDLE ((uint32_t)(USART_CR1_REG_INDEX << 28U | USART_CR1_IDLEIE)) +#define USART_IT_ERR ((uint32_t)(USART_CR3_REG_INDEX << 28U | USART_CR3_EIE)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup USART_Exported_Macros USART Exported Macros + * @{ + */ + +/** @brief Reset USART handle state + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +#define __HAL_USART_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->State = HAL_USART_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0U) +#else +#define __HAL_USART_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_USART_STATE_RESET) +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +/** @brief Check whether the specified USART flag is set or not. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg USART_FLAG_TXE: Transmit data register empty flag + * @arg USART_FLAG_TC: Transmission Complete flag + * @arg USART_FLAG_RXNE: Receive data register not empty flag + * @arg USART_FLAG_IDLE: Idle Line detection flag + * @arg USART_FLAG_ORE: Overrun Error flag + * @arg USART_FLAG_NE: Noise Error flag + * @arg USART_FLAG_FE: Framing Error flag + * @arg USART_FLAG_PE: Parity Error flag + * @retval The new state of __FLAG__ (TRUE or FALSE). + */ +#define __HAL_USART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** @brief Clear the specified USART pending flags. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __FLAG__ specifies the flag to check. + * This parameter can be any combination of the following values: + * @arg USART_FLAG_TC: Transmission Complete flag. + * @arg USART_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_USART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Clear the USART PE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_CLEAR_PEFLAG(__HANDLE__) \ + do{ \ + __IO uint32_t tmpreg = 0x00U; \ + tmpreg = (__HANDLE__)->Instance->SR; \ + tmpreg = (__HANDLE__)->Instance->DR; \ + UNUSED(tmpreg); \ + } while(0U) + +/** @brief Clear the USART FE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_CLEAR_FEFLAG(__HANDLE__) __HAL_USART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the USART NE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_CLEAR_NEFLAG(__HANDLE__) __HAL_USART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the USART ORE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_CLEAR_OREFLAG(__HANDLE__) __HAL_USART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Clear the USART IDLE pending flag. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_USART_CLEAR_PEFLAG(__HANDLE__) + +/** @brief Enables or disables the specified USART interrupts. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __INTERRUPT__ specifies the USART interrupt source to check. + * This parameter can be one of the following values: + * @arg USART_IT_TXE: Transmit Data Register empty interrupt + * @arg USART_IT_TC: Transmission complete interrupt + * @arg USART_IT_RXNE: Receive Data register not empty interrupt + * @arg USART_IT_IDLE: Idle line detection interrupt + * @arg USART_IT_PE: Parity Error interrupt + * @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) + * @retval None + */ +#define __HAL_USART_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == USART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 |= ((__INTERRUPT__) & USART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == USART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 |= ((__INTERRUPT__) & USART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 |= ((__INTERRUPT__) & USART_IT_MASK))) +#define __HAL_USART_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((((__INTERRUPT__) >> 28U) == USART_CR1_REG_INDEX)? ((__HANDLE__)->Instance->CR1 &= ~((__INTERRUPT__) & USART_IT_MASK)): \ + (((__INTERRUPT__) >> 28U) == USART_CR2_REG_INDEX)? ((__HANDLE__)->Instance->CR2 &= ~((__INTERRUPT__) & USART_IT_MASK)): \ + ((__HANDLE__)->Instance->CR3 &= ~ ((__INTERRUPT__) & USART_IT_MASK))) + +/** @brief Checks whether the specified USART interrupt has occurred or not. + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @param __IT__ specifies the USART interrupt source to check. + * This parameter can be one of the following values: + * @arg USART_IT_TXE: Transmit Data Register empty interrupt + * @arg USART_IT_TC: Transmission complete interrupt + * @arg USART_IT_RXNE: Receive Data register not empty interrupt + * @arg USART_IT_IDLE: Idle line detection interrupt + * @arg USART_IT_ERR: Error interrupt + * @arg USART_IT_PE: Parity Error interrupt + * @retval The new state of __IT__ (TRUE or FALSE). + */ +#define __HAL_USART_GET_IT_SOURCE(__HANDLE__, __IT__) (((((__IT__) >> 28U) == USART_CR1_REG_INDEX)? (__HANDLE__)->Instance->CR1:(((((uint32_t)(__IT__)) >> 28U) == USART_CR2_REG_INDEX)? \ + (__HANDLE__)->Instance->CR2 : (__HANDLE__)->Instance->CR3)) & (((uint32_t)(__IT__)) & USART_IT_MASK)) + +/** @brief Macro to enable the USART's one bit sample method + * @param __HANDLE__ specifies the USART Handle. + * @retval None + */ +#define __HAL_USART_ONE_BIT_SAMPLE_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3 |= USART_CR3_ONEBIT) + +/** @brief Macro to disable the USART's one bit sample method + * @param __HANDLE__ specifies the USART Handle. + * @retval None + */ +#define __HAL_USART_ONE_BIT_SAMPLE_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR3\ + &= (uint16_t)~((uint16_t)USART_CR3_ONEBIT)) + +/** @brief Enable USART + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 |= USART_CR1_UE) + +/** @brief Disable USART + * @param __HANDLE__ specifies the USART Handle. + * USART Handle selects the USARTx peripheral (USART availability and x value depending on device). + * @retval None + */ +#define __HAL_USART_DISABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1 &= ~USART_CR1_UE) + +/** + * @} + */ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup USART_Exported_Functions + * @{ + */ + +/** @addtogroup USART_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart); +HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart); +void HAL_USART_MspInit(USART_HandleTypeDef *husart); +void HAL_USART_MspDeInit(USART_HandleTypeDef *husart); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID, + pUSART_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup USART_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size, uint32_t Timeout); +HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size); +HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size); +HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size); +HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size); +HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size); +HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart); +HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart); +HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart); +/* Transfer Abort functions */ +HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart); +HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart); + +void HAL_USART_IRQHandler(USART_HandleTypeDef *husart); +void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart); +void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart); +void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart); +void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart); +void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart); +void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart); +void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart); +/** + * @} + */ + +/** @addtogroup USART_Exported_Functions_Group3 + * @{ + */ +/* Peripheral State functions ************************************************/ +HAL_USART_StateTypeDef HAL_USART_GetState(const USART_HandleTypeDef *husart); +uint32_t HAL_USART_GetError(const USART_HandleTypeDef *husart); +/** + * @} + */ + +/** + * @} + */ +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup USART_Private_Constants USART Private Constants + * @{ + */ +/** @brief USART interruptions flag mask + * + */ +#define USART_IT_MASK ((uint32_t) USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | \ + USART_CR1_IDLEIE | USART_CR2_LBDIE | USART_CR3_CTSIE | USART_CR3_EIE ) + +#define USART_CR1_REG_INDEX 1U +#define USART_CR2_REG_INDEX 2U +#define USART_CR3_REG_INDEX 3U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup USART_Private_Macros USART Private Macros + * @{ + */ +#define IS_USART_NACK_STATE(NACK) (((NACK) == USART_NACK_ENABLE) || \ + ((NACK) == USART_NACK_DISABLE)) + +#define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LASTBIT_DISABLE) || \ + ((LASTBIT) == USART_LASTBIT_ENABLE)) + +#define IS_USART_PHASE(CPHA) (((CPHA) == USART_PHASE_1EDGE) || \ + ((CPHA) == USART_PHASE_2EDGE)) + +#define IS_USART_POLARITY(CPOL) (((CPOL) == USART_POLARITY_LOW) || \ + ((CPOL) == USART_POLARITY_HIGH)) + +#define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_CLOCK_DISABLE) || \ + ((CLOCK) == USART_CLOCK_ENABLE)) + +#define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WORDLENGTH_8B) || \ + ((LENGTH) == USART_WORDLENGTH_9B)) + +#define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_STOPBITS_1) || \ + ((STOPBITS) == USART_STOPBITS_0_5) || \ + ((STOPBITS) == USART_STOPBITS_1_5) || \ + ((STOPBITS) == USART_STOPBITS_2)) + +#define IS_USART_PARITY(PARITY) (((PARITY) == USART_PARITY_NONE) || \ + ((PARITY) == USART_PARITY_EVEN) || \ + ((PARITY) == USART_PARITY_ODD)) + +#define IS_USART_MODE(MODE) ((((MODE) & (~((uint32_t)USART_MODE_TX_RX))) == 0x00U) && ((MODE) != 0x00U)) + +#define IS_USART_BAUDRATE(BAUDRATE) ((BAUDRATE) <= 12500000U) + +#define USART_DIV(_PCLK_, _BAUD_) ((uint32_t)((((uint64_t)(_PCLK_))*25U)/(2U*((uint64_t)(_BAUD_))))) + +#define USART_DIVMANT(_PCLK_, _BAUD_) (USART_DIV((_PCLK_), (_BAUD_))/100U) + +#define USART_DIVFRAQ(_PCLK_, _BAUD_) ((((USART_DIV((_PCLK_), (_BAUD_)) - (USART_DIVMANT((_PCLK_), (_BAUD_)) * 100U)) * 8U) + 50U) / 100U) + + /* UART BRR = mantissa + overflow + fraction + = (UART DIVMANT << 4) + ((UART DIVFRAQ & 0xF8) << 1) + (UART DIVFRAQ & 0x07U) */ + +#define USART_BRR(_PCLK_, _BAUD_) (((USART_DIVMANT((_PCLK_), (_BAUD_)) << 4U) + \ + ((USART_DIVFRAQ((_PCLK_), (_BAUD_)) & 0xF8U) << 1U)) + \ + (USART_DIVFRAQ((_PCLK_), (_BAUD_)) & 0x07U)) +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup USART_Private_Functions USART Private Functions + * @{ + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_HAL_USART_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h new file mode 100644 index 0000000..ab8b1ea --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_wwdg.h @@ -0,0 +1,298 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_wwdg.h + * @author MCD Application Team + * @brief Header file of WWDG 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 STM32F4xx_HAL_WWDG_H +#define STM32F4xx_HAL_WWDG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup WWDG + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ + +/** @defgroup WWDG_Exported_Types WWDG Exported Types + * @{ + */ + +/** + * @brief WWDG Init structure definition + */ +typedef struct +{ + uint32_t Prescaler; /*!< Specifies the prescaler value of the WWDG. + This parameter can be a value of @ref WWDG_Prescaler */ + + uint32_t Window; /*!< Specifies the WWDG window value to be compared to the downcounter. + This parameter must be a number Min_Data = 0x40 and Max_Data = 0x7F */ + + uint32_t Counter; /*!< Specifies the WWDG free-running downcounter value. + This parameter must be a number between Min_Data = 0x40 and Max_Data = 0x7F */ + + uint32_t EWIMode ; /*!< Specifies if WWDG Early Wakeup Interrupt is enable or not. + This parameter can be a value of @ref WWDG_EWI_Mode */ + +} WWDG_InitTypeDef; + +/** + * @brief WWDG handle Structure definition + */ +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) +typedef struct __WWDG_HandleTypeDef +#else +typedef struct +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ +{ + WWDG_TypeDef *Instance; /*!< Register base address */ + + WWDG_InitTypeDef Init; /*!< WWDG required parameters */ + +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) + void (* EwiCallback)(struct __WWDG_HandleTypeDef *hwwdg); /*!< WWDG Early WakeUp Interrupt callback */ + + void (* MspInitCallback)(struct __WWDG_HandleTypeDef *hwwdg); /*!< WWDG Msp Init callback */ +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ +} WWDG_HandleTypeDef; + +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) +/** + * @brief HAL WWDG common Callback ID enumeration definition + */ +typedef enum +{ + HAL_WWDG_EWI_CB_ID = 0x00U, /*!< WWDG EWI callback ID */ + HAL_WWDG_MSPINIT_CB_ID = 0x01U, /*!< WWDG MspInit callback ID */ +} HAL_WWDG_CallbackIDTypeDef; + +/** + * @brief HAL WWDG Callback pointer definition + */ +typedef void (*pWWDG_CallbackTypeDef)(WWDG_HandleTypeDef *hppp); /*!< pointer to a WWDG common callback functions */ + +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ + +/** @defgroup WWDG_Exported_Constants WWDG Exported Constants + * @{ + */ + +/** @defgroup WWDG_Interrupt_definition WWDG Interrupt definition + * @{ + */ +#define WWDG_IT_EWI WWDG_CFR_EWI /*!< Early wakeup interrupt */ +/** + * @} + */ + +/** @defgroup WWDG_Flag_definition WWDG Flag definition + * @brief WWDG Flag definition + * @{ + */ +#define WWDG_FLAG_EWIF WWDG_SR_EWIF /*!< Early wakeup interrupt flag */ +/** + * @} + */ + +/** @defgroup WWDG_Prescaler WWDG Prescaler + * @{ + */ +#define WWDG_PRESCALER_1 0x00000000u /*!< WWDG counter clock = (PCLK1/4096)/1 */ +#define WWDG_PRESCALER_2 WWDG_CFR_WDGTB_0 /*!< WWDG counter clock = (PCLK1/4096)/2 */ +#define WWDG_PRESCALER_4 WWDG_CFR_WDGTB_1 /*!< WWDG counter clock = (PCLK1/4096)/4 */ +#define WWDG_PRESCALER_8 (WWDG_CFR_WDGTB_1 | WWDG_CFR_WDGTB_0) /*!< WWDG counter clock = (PCLK1/4096)/8 */ +/** + * @} + */ + +/** @defgroup WWDG_EWI_Mode WWDG Early Wakeup Interrupt Mode + * @{ + */ +#define WWDG_EWI_DISABLE 0x00000000u /*!< EWI Disable */ +#define WWDG_EWI_ENABLE WWDG_CFR_EWI /*!< EWI Enable */ +/** + * @} + */ + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ + +/** @defgroup WWDG_Private_Macros WWDG Private Macros + * @{ + */ +#define IS_WWDG_PRESCALER(__PRESCALER__) (((__PRESCALER__) == WWDG_PRESCALER_1) || \ + ((__PRESCALER__) == WWDG_PRESCALER_2) || \ + ((__PRESCALER__) == WWDG_PRESCALER_4) || \ + ((__PRESCALER__) == WWDG_PRESCALER_8)) + +#define IS_WWDG_WINDOW(__WINDOW__) (((__WINDOW__) >= WWDG_CFR_W_6) && ((__WINDOW__) <= WWDG_CFR_W)) + +#define IS_WWDG_COUNTER(__COUNTER__) (((__COUNTER__) >= WWDG_CR_T_6) && ((__COUNTER__) <= WWDG_CR_T)) + +#define IS_WWDG_EWI_MODE(__MODE__) (((__MODE__) == WWDG_EWI_ENABLE) || \ + ((__MODE__) == WWDG_EWI_DISABLE)) +/** + * @} + */ + + +/* Exported macros ------------------------------------------------------------*/ + +/** @defgroup WWDG_Exported_Macros WWDG Exported Macros + * @{ + */ + +/** + * @brief Enable the WWDG peripheral. + * @param __HANDLE__ WWDG handle + * @retval None + */ +#define __HAL_WWDG_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR, WWDG_CR_WDGA) + +/** + * @brief Enable the WWDG early wakeup interrupt. + * @param __HANDLE__ WWDG handle + * @param __INTERRUPT__ specifies the interrupt to enable. + * This parameter can be one of the following values: + * @arg WWDG_IT_EWI: Early wakeup interrupt + * @note Once enabled this interrupt cannot be disabled except by a system reset. + * @retval None + */ +#define __HAL_WWDG_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CFR, (__INTERRUPT__)) + +/** + * @brief Check whether the selected WWDG interrupt has occurred or not. + * @param __HANDLE__ WWDG handle + * @param __INTERRUPT__ specifies the it to check. + * This parameter can be one of the following values: + * @arg WWDG_FLAG_EWIF: Early wakeup interrupt IT + * @retval The new state of WWDG_FLAG (SET or RESET). + */ +#define __HAL_WWDG_GET_IT(__HANDLE__, __INTERRUPT__) __HAL_WWDG_GET_FLAG((__HANDLE__),(__INTERRUPT__)) + +/** @brief Clear the WWDG interrupt pending bits. + * bits to clear the selected interrupt pending bits. + * @param __HANDLE__ WWDG handle + * @param __INTERRUPT__ specifies the interrupt pending bit to clear. + * This parameter can be one of the following values: + * @arg WWDG_FLAG_EWIF: Early wakeup interrupt flag + */ +#define __HAL_WWDG_CLEAR_IT(__HANDLE__, __INTERRUPT__) __HAL_WWDG_CLEAR_FLAG((__HANDLE__), (__INTERRUPT__)) + +/** + * @brief Check whether the specified WWDG flag is set or not. + * @param __HANDLE__ WWDG handle + * @param __FLAG__ specifies the flag to check. + * This parameter can be one of the following values: + * @arg WWDG_FLAG_EWIF: Early wakeup interrupt flag + * @retval The new state of WWDG_FLAG (SET or RESET). + */ +#define __HAL_WWDG_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear the WWDG's pending flags. + * @param __HANDLE__ WWDG handle + * @param __FLAG__ specifies the flag to clear. + * This parameter can be one of the following values: + * @arg WWDG_FLAG_EWIF: Early wakeup interrupt flag + * @retval None + */ +#define __HAL_WWDG_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->SR = ~(__FLAG__)) + +/** @brief Check whether the specified WWDG interrupt source is enabled or not. + * @param __HANDLE__ WWDG Handle. + * @param __INTERRUPT__ specifies the WWDG interrupt source to check. + * This parameter can be one of the following values: + * @arg WWDG_IT_EWI: Early Wakeup Interrupt + * @retval state of __INTERRUPT__ (TRUE or FALSE). + */ +#define __HAL_WWDG_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->CFR\ + & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup WWDG_Exported_Functions + * @{ + */ + +/** @addtogroup WWDG_Exported_Functions_Group1 + * @{ + */ +/* Initialization/de-initialization functions **********************************/ +HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg); +void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg); +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_WWDG_RegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID, + pWWDG_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_WWDG_UnRegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup WWDG_Exported_Functions_Group2 + * @{ + */ +/* I/O operation functions ******************************************************/ +HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg); +void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg); +void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_WWDG_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h new file mode 100644 index 0000000..43b4a1e --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_adc.h @@ -0,0 +1,4782 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_adc.h + * @author MCD Application Team + * @brief Header file of ADC LL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 __STM32F4xx_LL_ADC_H +#define __STM32F4xx_LL_ADC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (ADC1) || defined (ADC2) || defined (ADC3) + +/** @defgroup ADC_LL ADC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup ADC_LL_Private_Constants ADC Private Constants + * @{ + */ + +/* Internal mask for ADC group regular sequencer: */ +/* To select into literal LL_ADC_REG_RANK_x the relevant bits for: */ +/* - sequencer register offset */ +/* - sequencer rank bits position into the selected register */ + +/* Internal register offset for ADC group regular sequencer configuration */ +/* (offset placed into a spare area of literal definition) */ +#define ADC_SQR1_REGOFFSET 0x00000000UL +#define ADC_SQR2_REGOFFSET 0x00000100UL +#define ADC_SQR3_REGOFFSET 0x00000200UL +#define ADC_SQR4_REGOFFSET 0x00000300UL + +#define ADC_REG_SQRX_REGOFFSET_MASK (ADC_SQR1_REGOFFSET | ADC_SQR2_REGOFFSET | ADC_SQR3_REGOFFSET | ADC_SQR4_REGOFFSET) +#define ADC_REG_RANK_ID_SQRX_MASK (ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0) + +/* Definition of ADC group regular sequencer bits information to be inserted */ +/* into ADC group regular sequencer ranks literals definition. */ +#define ADC_REG_RANK_1_SQRX_BITOFFSET_POS ( 0UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ1) */ +#define ADC_REG_RANK_2_SQRX_BITOFFSET_POS ( 5UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ2) */ +#define ADC_REG_RANK_3_SQRX_BITOFFSET_POS (10UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ3) */ +#define ADC_REG_RANK_4_SQRX_BITOFFSET_POS (15UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ4) */ +#define ADC_REG_RANK_5_SQRX_BITOFFSET_POS (20UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ5) */ +#define ADC_REG_RANK_6_SQRX_BITOFFSET_POS (25UL) /* Value equivalent to POSITION_VAL(ADC_SQR3_SQ6) */ +#define ADC_REG_RANK_7_SQRX_BITOFFSET_POS ( 0UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ7) */ +#define ADC_REG_RANK_8_SQRX_BITOFFSET_POS ( 5UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ8) */ +#define ADC_REG_RANK_9_SQRX_BITOFFSET_POS (10UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ9) */ +#define ADC_REG_RANK_10_SQRX_BITOFFSET_POS (15UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ10) */ +#define ADC_REG_RANK_11_SQRX_BITOFFSET_POS (20UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ11) */ +#define ADC_REG_RANK_12_SQRX_BITOFFSET_POS (25UL) /* Value equivalent to POSITION_VAL(ADC_SQR2_SQ12) */ +#define ADC_REG_RANK_13_SQRX_BITOFFSET_POS ( 0UL) /* Value equivalent to POSITION_VAL(ADC_SQR1_SQ13) */ +#define ADC_REG_RANK_14_SQRX_BITOFFSET_POS ( 5UL) /* Value equivalent to POSITION_VAL(ADC_SQR1_SQ14) */ +#define ADC_REG_RANK_15_SQRX_BITOFFSET_POS (10UL) /* Value equivalent to POSITION_VAL(ADC_SQR1_SQ15) */ +#define ADC_REG_RANK_16_SQRX_BITOFFSET_POS (15UL) /* Value equivalent to POSITION_VAL(ADC_SQR1_SQ16) */ + +/* Internal mask for ADC group injected sequencer: */ +/* To select into literal LL_ADC_INJ_RANK_x the relevant bits for: */ +/* - data register offset */ +/* - offset register offset */ +/* - sequencer rank bits position into the selected register */ + +/* Internal register offset for ADC group injected data register */ +/* (offset placed into a spare area of literal definition) */ +#define ADC_JDR1_REGOFFSET 0x00000000UL +#define ADC_JDR2_REGOFFSET 0x00000100UL +#define ADC_JDR3_REGOFFSET 0x00000200UL +#define ADC_JDR4_REGOFFSET 0x00000300UL + +/* Internal register offset for ADC group injected offset configuration */ +/* (offset placed into a spare area of literal definition) */ +#define ADC_JOFR1_REGOFFSET 0x00000000UL +#define ADC_JOFR2_REGOFFSET 0x00001000UL +#define ADC_JOFR3_REGOFFSET 0x00002000UL +#define ADC_JOFR4_REGOFFSET 0x00003000UL + +#define ADC_INJ_JDRX_REGOFFSET_MASK (ADC_JDR1_REGOFFSET | ADC_JDR2_REGOFFSET | ADC_JDR3_REGOFFSET | ADC_JDR4_REGOFFSET) +#define ADC_INJ_JOFRX_REGOFFSET_MASK (ADC_JOFR1_REGOFFSET | ADC_JOFR2_REGOFFSET | ADC_JOFR3_REGOFFSET | ADC_JOFR4_REGOFFSET) +#define ADC_INJ_RANK_ID_JSQR_MASK (ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0) + +/* Internal mask for ADC group regular trigger: */ +/* To select into literal LL_ADC_REG_TRIG_x the relevant bits for: */ +/* - regular trigger source */ +/* - regular trigger edge */ +#define ADC_REG_TRIG_EXT_EDGE_DEFAULT (ADC_CR2_EXTEN_0) /* Trigger edge set to rising edge (default setting for compatibility with some ADC on other STM32 families having this setting set by HW default value) */ + +/* Mask containing trigger source masks for each of possible */ +/* trigger edge selection duplicated with shifts [0; 4; 8; 12] */ +/* corresponding to {SW start; ext trigger; ext trigger; ext trigger}. */ +#define ADC_REG_TRIG_SOURCE_MASK (((LL_ADC_REG_TRIG_SOFTWARE & ADC_CR2_EXTSEL) >> (4UL * 0UL)) | \ + ((ADC_CR2_EXTSEL) >> (4UL * 1UL)) | \ + ((ADC_CR2_EXTSEL) >> (4UL * 2UL)) | \ + ((ADC_CR2_EXTSEL) >> (4UL * 3UL))) + +/* Mask containing trigger edge masks for each of possible */ +/* trigger edge selection duplicated with shifts [0; 4; 8; 12] */ +/* corresponding to {SW start; ext trigger; ext trigger; ext trigger}. */ +#define ADC_REG_TRIG_EDGE_MASK (((LL_ADC_REG_TRIG_SOFTWARE & ADC_CR2_EXTEN) >> (4UL * 0UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 1UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 2UL)) | \ + ((ADC_REG_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 3UL))) + +/* Definition of ADC group regular trigger bits information. */ +#define ADC_REG_TRIG_EXTSEL_BITOFFSET_POS (24UL) /* Value equivalent to POSITION_VAL(ADC_CR2_EXTSEL) */ +#define ADC_REG_TRIG_EXTEN_BITOFFSET_POS (28UL) /* Value equivalent to POSITION_VAL(ADC_CR2_EXTEN) */ + + + +/* Internal mask for ADC group injected trigger: */ +/* To select into literal LL_ADC_INJ_TRIG_x the relevant bits for: */ +/* - injected trigger source */ +/* - injected trigger edge */ +#define ADC_INJ_TRIG_EXT_EDGE_DEFAULT (ADC_CR2_JEXTEN_0) /* Trigger edge set to rising edge (default setting for compatibility with some ADC on other STM32 families having this setting set by HW default value) */ + +/* Mask containing trigger source masks for each of possible */ +/* trigger edge selection duplicated with shifts [0; 4; 8; 12] */ +/* corresponding to {SW start; ext trigger; ext trigger; ext trigger}. */ +#define ADC_INJ_TRIG_SOURCE_MASK (((LL_ADC_REG_TRIG_SOFTWARE & ADC_CR2_JEXTSEL) >> (4UL * 0UL)) | \ + ((ADC_CR2_JEXTSEL) >> (4UL * 1UL)) | \ + ((ADC_CR2_JEXTSEL) >> (4UL * 2UL)) | \ + ((ADC_CR2_JEXTSEL) >> (4UL * 3UL))) + +/* Mask containing trigger edge masks for each of possible */ +/* trigger edge selection duplicated with shifts [0; 4; 8; 12] */ +/* corresponding to {SW start; ext trigger; ext trigger; ext trigger}. */ +#define ADC_INJ_TRIG_EDGE_MASK (((LL_ADC_INJ_TRIG_SOFTWARE & ADC_CR2_JEXTEN) >> (4UL * 0UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 1UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 2UL)) | \ + ((ADC_INJ_TRIG_EXT_EDGE_DEFAULT) >> (4UL * 3UL))) + +/* Definition of ADC group injected trigger bits information. */ +#define ADC_INJ_TRIG_EXTSEL_BITOFFSET_POS (16UL) /* Value equivalent to POSITION_VAL(ADC_CR2_JEXTSEL) */ +#define ADC_INJ_TRIG_EXTEN_BITOFFSET_POS (20UL) /* Value equivalent to POSITION_VAL(ADC_CR2_JEXTEN) */ + +/* Internal mask for ADC channel: */ +/* To select into literal LL_ADC_CHANNEL_x the relevant bits for: */ +/* - channel identifier defined by number */ +/* - channel differentiation between external channels (connected to */ +/* GPIO pins) and internal channels (connected to internal paths) */ +/* - channel sampling time defined by SMPRx register offset */ +/* and SMPx bits positions into SMPRx register */ +#define ADC_CHANNEL_ID_NUMBER_MASK (ADC_CR1_AWDCH) +#define ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS ( 0UL)/* Value equivalent to POSITION_VAL(ADC_CHANNEL_ID_NUMBER_MASK) */ +#define ADC_CHANNEL_ID_MASK (ADC_CHANNEL_ID_NUMBER_MASK | ADC_CHANNEL_ID_INTERNAL_CH_MASK) +/* Equivalent mask of ADC_CHANNEL_NUMBER_MASK aligned on register LSB (bit 0) */ +#define ADC_CHANNEL_ID_NUMBER_MASK_POSBIT0 0x0000001FU /* Equivalent to shift: (ADC_CHANNEL_NUMBER_MASK >> POSITION_VAL(ADC_CHANNEL_NUMBER_MASK)) */ + +/* Channel differentiation between external and internal channels */ +#define ADC_CHANNEL_ID_INTERNAL_CH 0x80000000UL /* Marker of internal channel */ +#define ADC_CHANNEL_ID_INTERNAL_CH_2 0x40000000UL /* Marker of internal channel for other ADC instances, in case of different ADC internal channels mapped on same channel number on different ADC instances */ +#define ADC_CHANNEL_DIFFERENCIATION_TEMPSENSOR_VBAT 0x10000000U /* Dummy bit for driver internal usage, not used in ADC channel setting registers CR1 or SQRx */ +#define ADC_CHANNEL_ID_INTERNAL_CH_MASK (ADC_CHANNEL_ID_INTERNAL_CH | ADC_CHANNEL_ID_INTERNAL_CH_2 | ADC_CHANNEL_DIFFERENCIATION_TEMPSENSOR_VBAT) + +/* Internal register offset for ADC channel sampling time configuration */ +/* (offset placed into a spare area of literal definition) */ +#define ADC_SMPR1_REGOFFSET 0x00000000UL +#define ADC_SMPR2_REGOFFSET 0x02000000UL +#define ADC_CHANNEL_SMPRX_REGOFFSET_MASK (ADC_SMPR1_REGOFFSET | ADC_SMPR2_REGOFFSET) + +#define ADC_CHANNEL_SMPx_BITOFFSET_MASK 0x01F00000UL +#define ADC_CHANNEL_SMPx_BITOFFSET_POS (20UL) /* Value equivalent to POSITION_VAL(ADC_CHANNEL_SMPx_BITOFFSET_MASK) */ + +/* Definition of channels ID number information to be inserted into */ +/* channels literals definition. */ +#define ADC_CHANNEL_0_NUMBER 0x00000000UL +#define ADC_CHANNEL_1_NUMBER ( ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_2_NUMBER ( ADC_CR1_AWDCH_1 ) +#define ADC_CHANNEL_3_NUMBER ( ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_4_NUMBER ( ADC_CR1_AWDCH_2 ) +#define ADC_CHANNEL_5_NUMBER ( ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_6_NUMBER ( ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 ) +#define ADC_CHANNEL_7_NUMBER ( ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_8_NUMBER ( ADC_CR1_AWDCH_3 ) +#define ADC_CHANNEL_9_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_10_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1 ) +#define ADC_CHANNEL_11_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_12_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 ) +#define ADC_CHANNEL_13_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_14_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 ) +#define ADC_CHANNEL_15_NUMBER ( ADC_CR1_AWDCH_3 | ADC_CR1_AWDCH_2 | ADC_CR1_AWDCH_1 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_16_NUMBER (ADC_CR1_AWDCH_4 ) +#define ADC_CHANNEL_17_NUMBER (ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_0) +#define ADC_CHANNEL_18_NUMBER (ADC_CR1_AWDCH_4 | ADC_CR1_AWDCH_1 ) + +/* Definition of channels sampling time information to be inserted into */ +/* channels literals definition. */ +#define ADC_CHANNEL_0_SMP (ADC_SMPR2_REGOFFSET | (( 0UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP0) */ +#define ADC_CHANNEL_1_SMP (ADC_SMPR2_REGOFFSET | (( 3UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP1) */ +#define ADC_CHANNEL_2_SMP (ADC_SMPR2_REGOFFSET | (( 6UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP2) */ +#define ADC_CHANNEL_3_SMP (ADC_SMPR2_REGOFFSET | (( 9UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP3) */ +#define ADC_CHANNEL_4_SMP (ADC_SMPR2_REGOFFSET | ((12UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP4) */ +#define ADC_CHANNEL_5_SMP (ADC_SMPR2_REGOFFSET | ((15UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP5) */ +#define ADC_CHANNEL_6_SMP (ADC_SMPR2_REGOFFSET | ((18UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP6) */ +#define ADC_CHANNEL_7_SMP (ADC_SMPR2_REGOFFSET | ((21UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP7) */ +#define ADC_CHANNEL_8_SMP (ADC_SMPR2_REGOFFSET | ((24UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP8) */ +#define ADC_CHANNEL_9_SMP (ADC_SMPR2_REGOFFSET | ((27UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR2_SMP9) */ +#define ADC_CHANNEL_10_SMP (ADC_SMPR1_REGOFFSET | (( 0UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP10) */ +#define ADC_CHANNEL_11_SMP (ADC_SMPR1_REGOFFSET | (( 3UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP11) */ +#define ADC_CHANNEL_12_SMP (ADC_SMPR1_REGOFFSET | (( 6UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP12) */ +#define ADC_CHANNEL_13_SMP (ADC_SMPR1_REGOFFSET | (( 9UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP13) */ +#define ADC_CHANNEL_14_SMP (ADC_SMPR1_REGOFFSET | ((12UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP14) */ +#define ADC_CHANNEL_15_SMP (ADC_SMPR1_REGOFFSET | ((15UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP15) */ +#define ADC_CHANNEL_16_SMP (ADC_SMPR1_REGOFFSET | ((18UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP16) */ +#define ADC_CHANNEL_17_SMP (ADC_SMPR1_REGOFFSET | ((21UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP17) */ +#define ADC_CHANNEL_18_SMP (ADC_SMPR1_REGOFFSET | ((24UL) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) /* Value shifted is equivalent to POSITION_VAL(ADC_SMPR1_SMP18) */ + +/* Internal mask for ADC analog watchdog: */ +/* To select into literals LL_ADC_AWD_CHANNELx_xxx the relevant bits for: */ +/* (concatenation of multiple bits used in different analog watchdogs, */ +/* (feature of several watchdogs not available on all STM32 families)). */ +/* - analog watchdog 1: monitored channel defined by number, */ +/* selection of ADC group (ADC groups regular and-or injected). */ + +/* Internal register offset for ADC analog watchdog channel configuration */ +#define ADC_AWD_CR1_REGOFFSET 0x00000000UL + +#define ADC_AWD_CRX_REGOFFSET_MASK (ADC_AWD_CR1_REGOFFSET) + +#define ADC_AWD_CR1_CHANNEL_MASK (ADC_CR1_AWDCH | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) +#define ADC_AWD_CR_ALL_CHANNEL_MASK (ADC_AWD_CR1_CHANNEL_MASK) + +/* Internal register offset for ADC analog watchdog threshold configuration */ +#define ADC_AWD_TR1_HIGH_REGOFFSET 0x00000000UL +#define ADC_AWD_TR1_LOW_REGOFFSET 0x00000001UL +#define ADC_AWD_TRX_REGOFFSET_MASK (ADC_AWD_TR1_HIGH_REGOFFSET | ADC_AWD_TR1_LOW_REGOFFSET) + +/* ADC registers bits positions */ +#define ADC_CR1_RES_BITOFFSET_POS (24UL) /* Value equivalent to POSITION_VAL(ADC_CR1_RES) */ +#define ADC_TR_HT_BITOFFSET_POS (16UL) /* Value equivalent to POSITION_VAL(ADC_TR_HT) */ + +/* ADC internal channels related definitions */ +/* Internal voltage reference VrefInt */ +#define VREFINT_CAL_ADDR ((uint16_t*) (0x1FFF7A2AU)) /* Internal voltage reference, address of parameter VREFINT_CAL: VrefInt ADC raw data acquired at temperature 30 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */ +#define VREFINT_CAL_VREF ( 3300UL) /* Analog voltage reference (Vref+) value with which temperature sensor has been calibrated in production (tolerance: +-10 mV) (unit: mV). */ +/* Temperature sensor */ +#define TEMPSENSOR_CAL1_ADDR ((uint16_t*) (0x1FFF7A2CU)) /* Internal temperature sensor, address of parameter TS_CAL1: On STM32F4, temperature sensor ADC raw data acquired at temperature 30 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */ +#define TEMPSENSOR_CAL2_ADDR ((uint16_t*) (0x1FFF7A2EU)) /* Internal temperature sensor, address of parameter TS_CAL2: On STM32F4, temperature sensor ADC raw data acquired at temperature 110 DegC (tolerance: +-5 DegC), Vref+ = 3.3 V (tolerance: +-10 mV). */ +#define TEMPSENSOR_CAL1_TEMP (( int32_t) 30) /* Internal temperature sensor, temperature at which temperature sensor has been calibrated in production for data into TEMPSENSOR_CAL1_ADDR (tolerance: +-5 DegC) (unit: DegC). */ +#define TEMPSENSOR_CAL2_TEMP (( int32_t) 110) /* Internal temperature sensor, temperature at which temperature sensor has been calibrated in production for data into TEMPSENSOR_CAL2_ADDR (tolerance: +-5 DegC) (unit: DegC). */ +#define TEMPSENSOR_CAL_VREFANALOG ( 3300UL) /* Analog voltage reference (Vref+) voltage with which temperature sensor has been calibrated in production (+-10 mV) (unit: mV). */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ADC_LL_Private_Macros ADC Private Macros + * @{ + */ + +/** + * @brief Driver macro reserved for internal use: isolate bits with the + * selected mask and shift them to the register LSB + * (shift mask on register position bit 0). + * @param __BITS__ Bits in register 32 bits + * @param __MASK__ Mask in register 32 bits + * @retval Bits in register 32 bits + */ +#define __ADC_MASK_SHIFT(__BITS__, __MASK__) \ + (((__BITS__) & (__MASK__)) >> POSITION_VAL((__MASK__))) + +/** + * @brief Driver macro reserved for internal use: set a pointer to + * a register from a register basis from which an offset + * is applied. + * @param __REG__ Register basis from which the offset is applied. + * @param __REG_OFFFSET__ Offset to be applied (unit number of registers). + * @retval Pointer to register address + */ +#define __ADC_PTR_REG_OFFSET(__REG__, __REG_OFFFSET__) \ + ((__IO uint32_t *)((uint32_t) ((uint32_t)(&(__REG__)) + ((__REG_OFFFSET__) << 2UL)))) + +/** + * @} + */ + + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup ADC_LL_ES_INIT ADC Exported Init structure + * @{ + */ + +/** + * @brief Structure definition of some features of ADC common parameters + * and multimode + * (all ADC instances belonging to the same ADC common instance). + * @note The setting of these parameters by function @ref LL_ADC_CommonInit() + * is conditioned to ADC instances state (all ADC instances + * sharing the same ADC common instance): + * All ADC instances sharing the same ADC common instance must be + * disabled. + */ +typedef struct +{ + uint32_t CommonClock; /*!< Set parameter common to several ADC: Clock source and prescaler. + This parameter can be a value of @ref ADC_LL_EC_COMMON_CLOCK_SOURCE + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetCommonClock(). */ + +#if defined(ADC_MULTIMODE_SUPPORT) + uint32_t Multimode; /*!< Set ADC multimode configuration to operate in independent mode or multimode (for devices with several ADC instances). + This parameter can be a value of @ref ADC_LL_EC_MULTI_MODE + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetMultimode(). */ + + uint32_t MultiDMATransfer; /*!< Set ADC multimode conversion data transfer: no transfer or transfer by DMA. + This parameter can be a value of @ref ADC_LL_EC_MULTI_DMA_TRANSFER + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetMultiDMATransfer(). */ + + uint32_t MultiTwoSamplingDelay; /*!< Set ADC multimode delay between 2 sampling phases. + This parameter can be a value of @ref ADC_LL_EC_MULTI_TWOSMP_DELAY + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetMultiTwoSamplingDelay(). */ +#endif /* ADC_MULTIMODE_SUPPORT */ + +} LL_ADC_CommonInitTypeDef; + +/** + * @brief Structure definition of some features of ADC instance. + * @note These parameters have an impact on ADC scope: ADC instance. + * Affects both group regular and group injected (availability + * of ADC group injected depends on STM32 families). + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Instance . + * @note The setting of these parameters by function @ref LL_ADC_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + */ +typedef struct +{ + uint32_t Resolution; /*!< Set ADC resolution. + This parameter can be a value of @ref ADC_LL_EC_RESOLUTION + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetResolution(). */ + + uint32_t DataAlignment; /*!< Set ADC conversion data alignment. + This parameter can be a value of @ref ADC_LL_EC_DATA_ALIGN + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetDataAlignment(). */ + + uint32_t SequencersScanMode; /*!< Set ADC scan selection. + This parameter can be a value of @ref ADC_LL_EC_SCAN_SELECTION + + This feature can be modified afterwards using unitary function @ref LL_ADC_SetSequencersScanMode(). */ + +} LL_ADC_InitTypeDef; + +/** + * @brief Structure definition of some features of ADC group regular. + * @note These parameters have an impact on ADC scope: ADC group regular. + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Group_Regular + * (functions with prefix "REG"). + * @note The setting of these parameters by function @ref LL_ADC_REG_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + */ +typedef struct +{ + uint32_t TriggerSource; /*!< Set ADC group regular conversion trigger source: internal (SW start) or from external IP (timer event, external interrupt line). + This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_SOURCE + @note On this STM32 series, setting of external trigger edge is performed + using function @ref LL_ADC_REG_StartConversionExtTrig(). + + This feature can be modified afterwards using unitary function @ref LL_ADC_REG_SetTriggerSource(). */ + + uint32_t SequencerLength; /*!< Set ADC group regular sequencer length. + This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_SCAN_LENGTH + @note This parameter is discarded if scan mode is disabled (refer to parameter 'ADC_SequencersScanMode'). + + This feature can be modified afterwards using unitary function @ref LL_ADC_REG_SetSequencerLength(). */ + + uint32_t SequencerDiscont; /*!< Set ADC group regular sequencer discontinuous mode: sequence subdivided and scan conversions interrupted every selected number of ranks. + This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_DISCONT_MODE + @note This parameter has an effect only if group regular sequencer is enabled + (scan length of 2 ranks or more). + + This feature can be modified afterwards using unitary function @ref LL_ADC_REG_SetSequencerDiscont(). */ + + uint32_t ContinuousMode; /*!< Set ADC continuous conversion mode on ADC group regular, whether ADC conversions are performed in single mode (one conversion per trigger) or in continuous mode (after the first trigger, following conversions launched successively automatically). + This parameter can be a value of @ref ADC_LL_EC_REG_CONTINUOUS_MODE + Note: It is not possible to enable both ADC group regular continuous mode and discontinuous mode. + + This feature can be modified afterwards using unitary function @ref LL_ADC_REG_SetContinuousMode(). */ + + uint32_t DMATransfer; /*!< Set ADC group regular conversion data transfer: no transfer or transfer by DMA, and DMA requests mode. + This parameter can be a value of @ref ADC_LL_EC_REG_DMA_TRANSFER + + This feature can be modified afterwards using unitary function @ref LL_ADC_REG_SetDMATransfer(). */ + +} LL_ADC_REG_InitTypeDef; + +/** + * @brief Structure definition of some features of ADC group injected. + * @note These parameters have an impact on ADC scope: ADC group injected. + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Group_Regular + * (functions with prefix "INJ"). + * @note The setting of these parameters by function @ref LL_ADC_INJ_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + */ +typedef struct +{ + uint32_t TriggerSource; /*!< Set ADC group injected conversion trigger source: internal (SW start) or from external IP (timer event, external interrupt line). + This parameter can be a value of @ref ADC_LL_EC_INJ_TRIGGER_SOURCE + @note On this STM32 series, setting of external trigger edge is performed + using function @ref LL_ADC_INJ_StartConversionExtTrig(). + + This feature can be modified afterwards using unitary function @ref LL_ADC_INJ_SetTriggerSource(). */ + + uint32_t SequencerLength; /*!< Set ADC group injected sequencer length. + This parameter can be a value of @ref ADC_LL_EC_INJ_SEQ_SCAN_LENGTH + @note This parameter is discarded if scan mode is disabled (refer to parameter 'ADC_SequencersScanMode'). + + This feature can be modified afterwards using unitary function @ref LL_ADC_INJ_SetSequencerLength(). */ + + uint32_t SequencerDiscont; /*!< Set ADC group injected sequencer discontinuous mode: sequence subdivided and scan conversions interrupted every selected number of ranks. + This parameter can be a value of @ref ADC_LL_EC_INJ_SEQ_DISCONT_MODE + @note This parameter has an effect only if group injected sequencer is enabled + (scan length of 2 ranks or more). + + This feature can be modified afterwards using unitary function @ref LL_ADC_INJ_SetSequencerDiscont(). */ + + uint32_t TrigAuto; /*!< Set ADC group injected conversion trigger: independent or from ADC group regular. + This parameter can be a value of @ref ADC_LL_EC_INJ_TRIG_AUTO + Note: This parameter must be set to set to independent trigger if injected trigger source is set to an external trigger. + + This feature can be modified afterwards using unitary function @ref LL_ADC_INJ_SetTrigAuto(). */ + +} LL_ADC_INJ_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ADC_LL_Exported_Constants ADC Exported Constants + * @{ + */ + +/** @defgroup ADC_LL_EC_FLAG ADC flags + * @brief Flags defines which can be used with LL_ADC_ReadReg function + * @{ + */ +#define LL_ADC_FLAG_STRT ADC_SR_STRT /*!< ADC flag ADC group regular conversion start */ +#define LL_ADC_FLAG_EOCS ADC_SR_EOC /*!< ADC flag ADC group regular end of unitary conversion or sequence conversions (to configure flag of end of conversion, use function @ref LL_ADC_REG_SetFlagEndOfConversion() ) */ +#define LL_ADC_FLAG_OVR ADC_SR_OVR /*!< ADC flag ADC group regular overrun */ +#define LL_ADC_FLAG_JSTRT ADC_SR_JSTRT /*!< ADC flag ADC group injected conversion start */ +#define LL_ADC_FLAG_JEOS ADC_SR_JEOC /*!< ADC flag ADC group injected end of sequence conversions (Note: on this STM32 series, there is no flag ADC group injected end of unitary conversion. Flag noted as "JEOC" is corresponding to flag "JEOS" in other STM32 families) */ +#define LL_ADC_FLAG_AWD1 ADC_SR_AWD /*!< ADC flag ADC analog watchdog 1 */ +#if defined(ADC_MULTIMODE_SUPPORT) +#define LL_ADC_FLAG_EOCS_MST ADC_CSR_EOC1 /*!< ADC flag ADC multimode master group regular end of unitary conversion or sequence conversions (to configure flag of end of conversion, use function @ref LL_ADC_REG_SetFlagEndOfConversion() ) */ +#define LL_ADC_FLAG_EOCS_SLV1 ADC_CSR_EOC2 /*!< ADC flag ADC multimode slave 1 group regular end of unitary conversion or sequence conversions (to configure flag of end of conversion, use function @ref LL_ADC_REG_SetFlagEndOfConversion() ) */ +#define LL_ADC_FLAG_EOCS_SLV2 ADC_CSR_EOC3 /*!< ADC flag ADC multimode slave 2 group regular end of unitary conversion or sequence conversions (to configure flag of end of conversion, use function @ref LL_ADC_REG_SetFlagEndOfConversion() ) */ +#define LL_ADC_FLAG_OVR_MST ADC_CSR_OVR1 /*!< ADC flag ADC multimode master group regular overrun */ +#define LL_ADC_FLAG_OVR_SLV1 ADC_CSR_OVR2 /*!< ADC flag ADC multimode slave 1 group regular overrun */ +#define LL_ADC_FLAG_OVR_SLV2 ADC_CSR_OVR3 /*!< ADC flag ADC multimode slave 2 group regular overrun */ +#define LL_ADC_FLAG_JEOS_MST ADC_CSR_JEOC1 /*!< ADC flag ADC multimode master group injected end of sequence conversions (Note: on this STM32 series, there is no flag ADC group injected end of unitary conversion. Flag noted as "JEOC" is corresponding to flag "JEOS" in other STM32 families) */ +#define LL_ADC_FLAG_JEOS_SLV1 ADC_CSR_JEOC2 /*!< ADC flag ADC multimode slave 1 group injected end of sequence conversions (Note: on this STM32 series, there is no flag ADC group injected end of unitary conversion. Flag noted as "JEOC" is corresponding to flag "JEOS" in other STM32 families) */ +#define LL_ADC_FLAG_JEOS_SLV2 ADC_CSR_JEOC3 /*!< ADC flag ADC multimode slave 2 group injected end of sequence conversions (Note: on this STM32 series, there is no flag ADC group injected end of unitary conversion. Flag noted as "JEOC" is corresponding to flag "JEOS" in other STM32 families) */ +#define LL_ADC_FLAG_AWD1_MST ADC_CSR_AWD1 /*!< ADC flag ADC multimode master analog watchdog 1 of the ADC master */ +#define LL_ADC_FLAG_AWD1_SLV1 ADC_CSR_AWD2 /*!< ADC flag ADC multimode slave 1 analog watchdog 1 */ +#define LL_ADC_FLAG_AWD1_SLV2 ADC_CSR_AWD3 /*!< ADC flag ADC multimode slave 2 analog watchdog 1 */ +#endif +/** + * @} + */ + +/** @defgroup ADC_LL_EC_IT ADC interruptions for configuration (interruption enable or disable) + * @brief IT defines which can be used with LL_ADC_ReadReg and LL_ADC_WriteReg functions + * @{ + */ +#define LL_ADC_IT_EOCS ADC_CR1_EOCIE /*!< ADC interruption ADC group regular end of unitary conversion or sequence conversions (to configure flag of end of conversion, use function @ref LL_ADC_REG_SetFlagEndOfConversion() ) */ +#define LL_ADC_IT_OVR ADC_CR1_OVRIE /*!< ADC interruption ADC group regular overrun */ +#define LL_ADC_IT_JEOS ADC_CR1_JEOCIE /*!< ADC interruption ADC group injected end of sequence conversions (Note: on this STM32 series, there is no flag ADC group injected end of unitary conversion. Flag noted as "JEOC" is corresponding to flag "JEOS" in other STM32 families) */ +#define LL_ADC_IT_AWD1 ADC_CR1_AWDIE /*!< ADC interruption ADC analog watchdog 1 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REGISTERS ADC registers compliant with specific purpose + * @{ + */ +/* List of ADC registers intended to be used (most commonly) with */ +/* DMA transfer. */ +/* Refer to function @ref LL_ADC_DMA_GetRegAddr(). */ +#define LL_ADC_DMA_REG_REGULAR_DATA 0x00000000UL /* ADC group regular conversion data register (corresponding to register DR) to be used with ADC configured in independent mode. Without DMA transfer, register accessed by LL function @ref LL_ADC_REG_ReadConversionData32() and other functions @ref LL_ADC_REG_ReadConversionDatax() */ +#if defined(ADC_MULTIMODE_SUPPORT) +#define LL_ADC_DMA_REG_REGULAR_DATA_MULTI 0x00000001UL /* ADC group regular conversion data register (corresponding to register CDR) to be used with ADC configured in multimode (available on STM32 devices with several ADC instances). Without DMA transfer, register accessed by LL function @ref LL_ADC_REG_ReadMultiConversionData32() */ +#endif +/** + * @} + */ + +/** @defgroup ADC_LL_EC_COMMON_CLOCK_SOURCE ADC common - Clock source + * @{ + */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV2 0x00000000UL /*!< ADC synchronous clock derived from AHB clock with prescaler division by 2 */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV4 ( ADC_CCR_ADCPRE_0) /*!< ADC synchronous clock derived from AHB clock with prescaler division by 4 */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV6 (ADC_CCR_ADCPRE_1 ) /*!< ADC synchronous clock derived from AHB clock with prescaler division by 6 */ +#define LL_ADC_CLOCK_SYNC_PCLK_DIV8 (ADC_CCR_ADCPRE_1 | ADC_CCR_ADCPRE_0) /*!< ADC synchronous clock derived from AHB clock with prescaler division by 8 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_COMMON_PATH_INTERNAL ADC common - Measurement path to internal channels + * @{ + */ +/* Note: Other measurement paths to internal channels may be available */ +/* (connections to other peripherals). */ +/* If they are not listed below, they do not require any specific */ +/* path enable. In this case, Access to measurement path is done */ +/* only by selecting the corresponding ADC internal channel. */ +#define LL_ADC_PATH_INTERNAL_NONE 0x00000000UL /*!< ADC measurement paths all disabled */ +#define LL_ADC_PATH_INTERNAL_VREFINT (ADC_CCR_TSVREFE) /*!< ADC measurement path to internal channel VrefInt */ +#define LL_ADC_PATH_INTERNAL_TEMPSENSOR (ADC_CCR_TSVREFE) /*!< ADC measurement path to internal channel temperature sensor */ +#define LL_ADC_PATH_INTERNAL_VBAT (ADC_CCR_VBATE) /*!< ADC measurement path to internal channel Vbat */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_RESOLUTION ADC instance - Resolution + * @{ + */ +#define LL_ADC_RESOLUTION_12B 0x00000000UL /*!< ADC resolution 12 bits */ +#define LL_ADC_RESOLUTION_10B ( ADC_CR1_RES_0) /*!< ADC resolution 10 bits */ +#define LL_ADC_RESOLUTION_8B (ADC_CR1_RES_1 ) /*!< ADC resolution 8 bits */ +#define LL_ADC_RESOLUTION_6B (ADC_CR1_RES_1 | ADC_CR1_RES_0) /*!< ADC resolution 6 bits */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_DATA_ALIGN ADC instance - Data alignment + * @{ + */ +#define LL_ADC_DATA_ALIGN_RIGHT 0x00000000UL /*!< ADC conversion data alignment: right aligned (alignment on data register LSB bit 0)*/ +#define LL_ADC_DATA_ALIGN_LEFT (ADC_CR2_ALIGN) /*!< ADC conversion data alignment: left aligned (alignment on data register MSB bit 15)*/ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_SCAN_SELECTION ADC instance - Scan selection + * @{ + */ +#define LL_ADC_SEQ_SCAN_DISABLE 0x00000000UL /*!< ADC conversion is performed in unitary conversion mode (one channel converted, that defined in rank 1). Configuration of both groups regular and injected sequencers (sequence length, ...) is discarded: equivalent to length of 1 rank.*/ +#define LL_ADC_SEQ_SCAN_ENABLE (ADC_CR1_SCAN) /*!< ADC conversions are performed in sequence conversions mode, according to configuration of both groups regular and injected sequencers (sequence length, ...). */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_GROUPS ADC instance - Groups + * @{ + */ +#define LL_ADC_GROUP_REGULAR 0x00000001UL /*!< ADC group regular (available on all STM32 devices) */ +#define LL_ADC_GROUP_INJECTED 0x00000002UL /*!< ADC group injected (not available on all STM32 devices)*/ +#define LL_ADC_GROUP_REGULAR_INJECTED 0x00000003UL /*!< ADC both groups regular and injected */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_CHANNEL ADC instance - Channel number + * @{ + */ +#define LL_ADC_CHANNEL_0 (ADC_CHANNEL_0_NUMBER | ADC_CHANNEL_0_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN0 */ +#define LL_ADC_CHANNEL_1 (ADC_CHANNEL_1_NUMBER | ADC_CHANNEL_1_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN1 */ +#define LL_ADC_CHANNEL_2 (ADC_CHANNEL_2_NUMBER | ADC_CHANNEL_2_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN2 */ +#define LL_ADC_CHANNEL_3 (ADC_CHANNEL_3_NUMBER | ADC_CHANNEL_3_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN3 */ +#define LL_ADC_CHANNEL_4 (ADC_CHANNEL_4_NUMBER | ADC_CHANNEL_4_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN4 */ +#define LL_ADC_CHANNEL_5 (ADC_CHANNEL_5_NUMBER | ADC_CHANNEL_5_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN5 */ +#define LL_ADC_CHANNEL_6 (ADC_CHANNEL_6_NUMBER | ADC_CHANNEL_6_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN6 */ +#define LL_ADC_CHANNEL_7 (ADC_CHANNEL_7_NUMBER | ADC_CHANNEL_7_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN7 */ +#define LL_ADC_CHANNEL_8 (ADC_CHANNEL_8_NUMBER | ADC_CHANNEL_8_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN8 */ +#define LL_ADC_CHANNEL_9 (ADC_CHANNEL_9_NUMBER | ADC_CHANNEL_9_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN9 */ +#define LL_ADC_CHANNEL_10 (ADC_CHANNEL_10_NUMBER | ADC_CHANNEL_10_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN10 */ +#define LL_ADC_CHANNEL_11 (ADC_CHANNEL_11_NUMBER | ADC_CHANNEL_11_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN11 */ +#define LL_ADC_CHANNEL_12 (ADC_CHANNEL_12_NUMBER | ADC_CHANNEL_12_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN12 */ +#define LL_ADC_CHANNEL_13 (ADC_CHANNEL_13_NUMBER | ADC_CHANNEL_13_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN13 */ +#define LL_ADC_CHANNEL_14 (ADC_CHANNEL_14_NUMBER | ADC_CHANNEL_14_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN14 */ +#define LL_ADC_CHANNEL_15 (ADC_CHANNEL_15_NUMBER | ADC_CHANNEL_15_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN15 */ +#define LL_ADC_CHANNEL_16 (ADC_CHANNEL_16_NUMBER | ADC_CHANNEL_16_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN16 */ +#define LL_ADC_CHANNEL_17 (ADC_CHANNEL_17_NUMBER | ADC_CHANNEL_17_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN17 */ +#define LL_ADC_CHANNEL_18 (ADC_CHANNEL_18_NUMBER | ADC_CHANNEL_18_SMP) /*!< ADC external channel (channel connected to GPIO pin) ADCx_IN18 */ +#define LL_ADC_CHANNEL_VREFINT (LL_ADC_CHANNEL_17 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel connected to VrefInt: Internal voltage reference. On STM32F4, ADC channel available only on ADC instance: ADC1. */ +#define LL_ADC_CHANNEL_VBAT (LL_ADC_CHANNEL_18 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel connected to Vbat/3: Vbat voltage through a divider ladder of factor 1/3 to have Vbat always below Vdda. On STM32F4, ADC channel available only on ADC instance: ADC1. */ +#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xx) || defined(STM32F407xx) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F415xx) || defined(STM32F417xx) +#define LL_ADC_CHANNEL_TEMPSENSOR (LL_ADC_CHANNEL_16 | ADC_CHANNEL_ID_INTERNAL_CH) /*!< ADC internal channel connected to Temperature sensor. On STM32F4, ADC channel available only on ADC instance: ADC1. */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE || STM32F410xx */ +#if defined(STM32F411xE) || defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || defined(STM32F423xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#define LL_ADC_CHANNEL_TEMPSENSOR (LL_ADC_CHANNEL_18 | ADC_CHANNEL_ID_INTERNAL_CH | ADC_CHANNEL_DIFFERENCIATION_TEMPSENSOR_VBAT) /*!< ADC internal channel connected to Temperature sensor. On STM32F4, ADC channel available only on ADC instance: ADC1. This internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. */ +#endif /* STM32F411xE || STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_TRIGGER_SOURCE ADC group regular - Trigger source + * @{ + */ +#define LL_ADC_REG_TRIG_SOFTWARE 0x00000000UL /*!< ADC group regular conversion trigger internal: SW start. */ +#define LL_ADC_REG_TRIG_EXT_TIM1_CH1 (ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM1 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM1_CH2 (ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM1 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM1_CH3 (ADC_CR2_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM1 channel 3 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM2_CH2 (ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM2 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM2_CH3 (ADC_CR2_EXTSEL_2 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM2 channel 3 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM2_CH4 (ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM2 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM2_TRGO (ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM2 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM3_CH1 (ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM3 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM3_TRGO (ADC_CR2_EXTSEL_3 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM3 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM4_CH4 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM4 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM5_CH1 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM5 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM5_CH2 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM5 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM5_CH3 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM5 channel 3 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM8_CH1 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM8 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_TIM8_TRGO (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: TIM8 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_REG_TRIG_EXT_EXTI_LINE11 (ADC_CR2_EXTSEL_3 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_0 | ADC_REG_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group regular conversion trigger from external IP: external interrupt line 11. Trigger edge set to rising edge (default setting). */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_TRIGGER_EDGE ADC group regular - Trigger edge + * @{ + */ +#define LL_ADC_REG_TRIG_EXT_RISING ( ADC_CR2_EXTEN_0) /*!< ADC group regular conversion trigger polarity set to rising edge */ +#define LL_ADC_REG_TRIG_EXT_FALLING (ADC_CR2_EXTEN_1 ) /*!< ADC group regular conversion trigger polarity set to falling edge */ +#define LL_ADC_REG_TRIG_EXT_RISINGFALLING (ADC_CR2_EXTEN_1 | ADC_CR2_EXTEN_0) /*!< ADC group regular conversion trigger polarity set to both rising and falling edges */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_CONTINUOUS_MODE ADC group regular - Continuous mode + * @{ + */ +#define LL_ADC_REG_CONV_SINGLE 0x00000000UL /*!< ADC conversions are performed in single mode: one conversion per trigger */ +#define LL_ADC_REG_CONV_CONTINUOUS (ADC_CR2_CONT) /*!< ADC conversions are performed in continuous mode: after the first trigger, following conversions launched successively automatically */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_DMA_TRANSFER ADC group regular - DMA transfer of ADC conversion data + * @{ + */ +#define LL_ADC_REG_DMA_TRANSFER_NONE 0x00000000UL /*!< ADC conversions are not transferred by DMA */ +#define LL_ADC_REG_DMA_TRANSFER_LIMITED ( ADC_CR2_DMA) /*!< ADC conversion data are transferred by DMA, in limited mode (one shot mode): DMA transfer requests are stopped when number of DMA data transfers (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. */ +#define LL_ADC_REG_DMA_TRANSFER_UNLIMITED (ADC_CR2_DDS | ADC_CR2_DMA) /*!< ADC conversion data are transferred by DMA, in unlimited mode: DMA transfer requests are unlimited, whatever number of DMA data transferred (number of ADC conversions). This ADC mode is intended to be used with DMA mode circular. */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_FLAG_EOC_SELECTION ADC group regular - Flag EOC selection (unitary or sequence conversions) + * @{ + */ +#define LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV 0x00000000UL /*!< ADC flag EOC (end of unitary conversion) selected */ +#define LL_ADC_REG_FLAG_EOC_UNITARY_CONV (ADC_CR2_EOCS) /*!< ADC flag EOS (end of sequence conversions) selected */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_SEQ_SCAN_LENGTH ADC group regular - Sequencer scan length + * @{ + */ +#define LL_ADC_REG_SEQ_SCAN_DISABLE 0x00000000UL /*!< ADC group regular sequencer disable (equivalent to sequencer of 1 rank: ADC conversion on only 1 channel) */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS ( ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 2 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS ( ADC_SQR1_L_1 ) /*!< ADC group regular sequencer enable with 3 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS ( ADC_SQR1_L_1 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 4 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS ( ADC_SQR1_L_2 ) /*!< ADC group regular sequencer enable with 5 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS ( ADC_SQR1_L_2 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 6 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS ( ADC_SQR1_L_2 | ADC_SQR1_L_1 ) /*!< ADC group regular sequencer enable with 7 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS ( ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 8 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS (ADC_SQR1_L_3 ) /*!< ADC group regular sequencer enable with 9 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 10 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_1 ) /*!< ADC group regular sequencer enable with 11 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_1 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 12 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_2 ) /*!< ADC group regular sequencer enable with 13 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_2 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 14 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_2 | ADC_SQR1_L_1 ) /*!< ADC group regular sequencer enable with 15 ranks in the sequence */ +#define LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS (ADC_SQR1_L_3 | ADC_SQR1_L_2 | ADC_SQR1_L_1 | ADC_SQR1_L_0) /*!< ADC group regular sequencer enable with 16 ranks in the sequence */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_SEQ_DISCONT_MODE ADC group regular - Sequencer discontinuous mode + * @{ + */ +#define LL_ADC_REG_SEQ_DISCONT_DISABLE 0x00000000UL /*!< ADC group regular sequencer discontinuous mode disable */ +#define LL_ADC_REG_SEQ_DISCONT_1RANK ( ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every rank */ +#define LL_ADC_REG_SEQ_DISCONT_2RANKS ( ADC_CR1_DISCNUM_0 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enabled with sequence interruption every 2 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_3RANKS ( ADC_CR1_DISCNUM_1 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 3 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_4RANKS ( ADC_CR1_DISCNUM_1 | ADC_CR1_DISCNUM_0 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 4 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_5RANKS (ADC_CR1_DISCNUM_2 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 5 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_6RANKS (ADC_CR1_DISCNUM_2 | ADC_CR1_DISCNUM_0 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 6 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_7RANKS (ADC_CR1_DISCNUM_2 | ADC_CR1_DISCNUM_1 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 7 ranks */ +#define LL_ADC_REG_SEQ_DISCONT_8RANKS (ADC_CR1_DISCNUM_2 | ADC_CR1_DISCNUM_1 | ADC_CR1_DISCNUM_0 | ADC_CR1_DISCEN) /*!< ADC group regular sequencer discontinuous mode enable with sequence interruption every 8 ranks */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_REG_SEQ_RANKS ADC group regular - Sequencer ranks + * @{ + */ +#define LL_ADC_REG_RANK_1 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_1_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 1 */ +#define LL_ADC_REG_RANK_2 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_2_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 2 */ +#define LL_ADC_REG_RANK_3 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_3_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 3 */ +#define LL_ADC_REG_RANK_4 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_4_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 4 */ +#define LL_ADC_REG_RANK_5 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_5_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 5 */ +#define LL_ADC_REG_RANK_6 (ADC_SQR3_REGOFFSET | ADC_REG_RANK_6_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 6 */ +#define LL_ADC_REG_RANK_7 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_7_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 7 */ +#define LL_ADC_REG_RANK_8 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_8_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 8 */ +#define LL_ADC_REG_RANK_9 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_9_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 9 */ +#define LL_ADC_REG_RANK_10 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_10_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 10 */ +#define LL_ADC_REG_RANK_11 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_11_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 11 */ +#define LL_ADC_REG_RANK_12 (ADC_SQR2_REGOFFSET | ADC_REG_RANK_12_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 12 */ +#define LL_ADC_REG_RANK_13 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_13_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 13 */ +#define LL_ADC_REG_RANK_14 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_14_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 14 */ +#define LL_ADC_REG_RANK_15 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_15_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 15 */ +#define LL_ADC_REG_RANK_16 (ADC_SQR1_REGOFFSET | ADC_REG_RANK_16_SQRX_BITOFFSET_POS) /*!< ADC group regular sequencer rank 16 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_INJ_TRIGGER_SOURCE ADC group injected - Trigger source + * @{ + */ +#define LL_ADC_INJ_TRIG_SOFTWARE 0x00000000UL /*!< ADC group injected conversion trigger internal: SW start. */ +#define LL_ADC_INJ_TRIG_EXT_TIM1_CH4 (ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM1 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM1_TRGO (ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM1 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM2_CH1 (ADC_CR2_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM2 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM2_TRGO (ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM2 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM3_CH2 (ADC_CR2_JEXTSEL_2 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM3 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM3_CH4 (ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM3 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM4_CH1 (ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM4 channel 1 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM4_CH2 (ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM4 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM4_CH3 (ADC_CR2_JEXTSEL_3 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM4 channel 3 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM4_TRGO (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM4 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM5_CH4 (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM5 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM5_TRGO (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM5 TRGO. Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM8_CH2 (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM8 channel 2 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM8_CH3 (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM8 channel 3 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_TIM8_CH4 (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: TIM8 channel 4 event (capture compare: input capture or output capture). Trigger edge set to rising edge (default setting). */ +#define LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 (ADC_CR2_JEXTSEL_3 | ADC_CR2_JEXTSEL_2 | ADC_CR2_JEXTSEL_1 | ADC_CR2_JEXTSEL_0 | ADC_INJ_TRIG_EXT_EDGE_DEFAULT) /*!< ADC group injected conversion trigger from external IP: external interrupt line 15. Trigger edge set to rising edge (default setting). */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_INJ_TRIGGER_EDGE ADC group injected - Trigger edge + * @{ + */ +#define LL_ADC_INJ_TRIG_EXT_RISING ( ADC_CR2_JEXTEN_0) /*!< ADC group injected conversion trigger polarity set to rising edge */ +#define LL_ADC_INJ_TRIG_EXT_FALLING (ADC_CR2_JEXTEN_1 ) /*!< ADC group injected conversion trigger polarity set to falling edge */ +#define LL_ADC_INJ_TRIG_EXT_RISINGFALLING (ADC_CR2_JEXTEN_1 | ADC_CR2_JEXTEN_0) /*!< ADC group injected conversion trigger polarity set to both rising and falling edges */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_INJ_TRIG_AUTO ADC group injected - Automatic trigger mode + * @{ + */ +#define LL_ADC_INJ_TRIG_INDEPENDENT 0x00000000UL /*!< ADC group injected conversion trigger independent. Setting mandatory if ADC group injected injected trigger source is set to an external trigger. */ +#define LL_ADC_INJ_TRIG_FROM_GRP_REGULAR (ADC_CR1_JAUTO) /*!< ADC group injected conversion trigger from ADC group regular. Setting compliant only with group injected trigger source set to SW start, without any further action on ADC group injected conversion start or stop: in this case, ADC group injected is controlled only from ADC group regular. */ +/** + * @} + */ + + +/** @defgroup ADC_LL_EC_INJ_SEQ_SCAN_LENGTH ADC group injected - Sequencer scan length + * @{ + */ +#define LL_ADC_INJ_SEQ_SCAN_DISABLE 0x00000000UL /*!< ADC group injected sequencer disable (equivalent to sequencer of 1 rank: ADC conversion on only 1 channel) */ +#define LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS ( ADC_JSQR_JL_0) /*!< ADC group injected sequencer enable with 2 ranks in the sequence */ +#define LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS (ADC_JSQR_JL_1 ) /*!< ADC group injected sequencer enable with 3 ranks in the sequence */ +#define LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS (ADC_JSQR_JL_1 | ADC_JSQR_JL_0) /*!< ADC group injected sequencer enable with 4 ranks in the sequence */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_INJ_SEQ_DISCONT_MODE ADC group injected - Sequencer discontinuous mode + * @{ + */ +#define LL_ADC_INJ_SEQ_DISCONT_DISABLE 0x00000000UL /*!< ADC group injected sequencer discontinuous mode disable */ +#define LL_ADC_INJ_SEQ_DISCONT_1RANK (ADC_CR1_JDISCEN) /*!< ADC group injected sequencer discontinuous mode enable with sequence interruption every rank */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_INJ_SEQ_RANKS ADC group injected - Sequencer ranks + * @{ + */ +#define LL_ADC_INJ_RANK_1 (ADC_JDR1_REGOFFSET | ADC_JOFR1_REGOFFSET | 0x00000001UL) /*!< ADC group injected sequencer rank 1 */ +#define LL_ADC_INJ_RANK_2 (ADC_JDR2_REGOFFSET | ADC_JOFR2_REGOFFSET | 0x00000002UL) /*!< ADC group injected sequencer rank 2 */ +#define LL_ADC_INJ_RANK_3 (ADC_JDR3_REGOFFSET | ADC_JOFR3_REGOFFSET | 0x00000003UL) /*!< ADC group injected sequencer rank 3 */ +#define LL_ADC_INJ_RANK_4 (ADC_JDR4_REGOFFSET | ADC_JOFR4_REGOFFSET | 0x00000004UL) /*!< ADC group injected sequencer rank 4 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_CHANNEL_SAMPLINGTIME Channel - Sampling time + * @{ + */ +#define LL_ADC_SAMPLINGTIME_3CYCLES 0x00000000UL /*!< Sampling time 3 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_15CYCLES (ADC_SMPR1_SMP10_0) /*!< Sampling time 15 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_28CYCLES (ADC_SMPR1_SMP10_1) /*!< Sampling time 28 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_56CYCLES (ADC_SMPR1_SMP10_1 | ADC_SMPR1_SMP10_0) /*!< Sampling time 56 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_84CYCLES (ADC_SMPR1_SMP10_2) /*!< Sampling time 84 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_112CYCLES (ADC_SMPR1_SMP10_2 | ADC_SMPR1_SMP10_0) /*!< Sampling time 112 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_144CYCLES (ADC_SMPR1_SMP10_2 | ADC_SMPR1_SMP10_1) /*!< Sampling time 144 ADC clock cycles */ +#define LL_ADC_SAMPLINGTIME_480CYCLES (ADC_SMPR1_SMP10) /*!< Sampling time 480 ADC clock cycles */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_AWD_NUMBER Analog watchdog - Analog watchdog number + * @{ + */ +#define LL_ADC_AWD1 (ADC_AWD_CR1_CHANNEL_MASK | ADC_AWD_CR1_REGOFFSET) /*!< ADC analog watchdog number 1 */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_AWD_CHANNELS Analog watchdog - Monitored channels + * @{ + */ +#define LL_ADC_AWD_DISABLE 0x00000000UL /*!< ADC analog watchdog monitoring disabled */ +#define LL_ADC_AWD_ALL_CHANNELS_REG ( ADC_CR1_AWDEN ) /*!< ADC analog watchdog monitoring of all channels, converted by group regular only */ +#define LL_ADC_AWD_ALL_CHANNELS_INJ ( ADC_CR1_JAWDEN ) /*!< ADC analog watchdog monitoring of all channels, converted by group injected only */ +#define LL_ADC_AWD_ALL_CHANNELS_REG_INJ ( ADC_CR1_JAWDEN | ADC_CR1_AWDEN ) /*!< ADC analog watchdog monitoring of all channels, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_0_REG ((LL_ADC_CHANNEL_0 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN0, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_0_INJ ((LL_ADC_CHANNEL_0 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN0, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_0_REG_INJ ((LL_ADC_CHANNEL_0 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN0, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_1_REG ((LL_ADC_CHANNEL_1 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN1, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_1_INJ ((LL_ADC_CHANNEL_1 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN1, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_1_REG_INJ ((LL_ADC_CHANNEL_1 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN1, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_2_REG ((LL_ADC_CHANNEL_2 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN2, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_2_INJ ((LL_ADC_CHANNEL_2 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN2, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_2_REG_INJ ((LL_ADC_CHANNEL_2 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN2, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_3_REG ((LL_ADC_CHANNEL_3 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN3, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_3_INJ ((LL_ADC_CHANNEL_3 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN3, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_3_REG_INJ ((LL_ADC_CHANNEL_3 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN3, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_4_REG ((LL_ADC_CHANNEL_4 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN4, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_4_INJ ((LL_ADC_CHANNEL_4 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN4, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_4_REG_INJ ((LL_ADC_CHANNEL_4 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN4, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_5_REG ((LL_ADC_CHANNEL_5 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN5, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_5_INJ ((LL_ADC_CHANNEL_5 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN5, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_5_REG_INJ ((LL_ADC_CHANNEL_5 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN5, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_6_REG ((LL_ADC_CHANNEL_6 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN6, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_6_INJ ((LL_ADC_CHANNEL_6 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN6, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_6_REG_INJ ((LL_ADC_CHANNEL_6 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN6, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_7_REG ((LL_ADC_CHANNEL_7 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN7, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_7_INJ ((LL_ADC_CHANNEL_7 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN7, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_7_REG_INJ ((LL_ADC_CHANNEL_7 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN7, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_8_REG ((LL_ADC_CHANNEL_8 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN8, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_8_INJ ((LL_ADC_CHANNEL_8 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN8, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_8_REG_INJ ((LL_ADC_CHANNEL_8 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN8, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_9_REG ((LL_ADC_CHANNEL_9 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN9, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_9_INJ ((LL_ADC_CHANNEL_9 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN9, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_9_REG_INJ ((LL_ADC_CHANNEL_9 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN9, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_10_REG ((LL_ADC_CHANNEL_10 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN10, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_10_INJ ((LL_ADC_CHANNEL_10 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN10, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_10_REG_INJ ((LL_ADC_CHANNEL_10 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN10, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_11_REG ((LL_ADC_CHANNEL_11 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN11, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_11_INJ ((LL_ADC_CHANNEL_11 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN11, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_11_REG_INJ ((LL_ADC_CHANNEL_11 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN11, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_12_REG ((LL_ADC_CHANNEL_12 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN12, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_12_INJ ((LL_ADC_CHANNEL_12 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN12, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_12_REG_INJ ((LL_ADC_CHANNEL_12 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN12, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_13_REG ((LL_ADC_CHANNEL_13 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN13, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_13_INJ ((LL_ADC_CHANNEL_13 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN13, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_13_REG_INJ ((LL_ADC_CHANNEL_13 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN13, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_14_REG ((LL_ADC_CHANNEL_14 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN14, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_14_INJ ((LL_ADC_CHANNEL_14 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN14, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_14_REG_INJ ((LL_ADC_CHANNEL_14 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN14, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_15_REG ((LL_ADC_CHANNEL_15 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN15, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_15_INJ ((LL_ADC_CHANNEL_15 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN15, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_15_REG_INJ ((LL_ADC_CHANNEL_15 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN15, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_16_REG ((LL_ADC_CHANNEL_16 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN16, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_16_INJ ((LL_ADC_CHANNEL_16 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN16, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_16_REG_INJ ((LL_ADC_CHANNEL_16 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN16, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_17_REG ((LL_ADC_CHANNEL_17 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN17, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_17_INJ ((LL_ADC_CHANNEL_17 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN17, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_17_REG_INJ ((LL_ADC_CHANNEL_17 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN17, converted by either group regular or injected */ +#define LL_ADC_AWD_CHANNEL_18_REG ((LL_ADC_CHANNEL_18 & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN18, converted by group regular only */ +#define LL_ADC_AWD_CHANNEL_18_INJ ((LL_ADC_CHANNEL_18 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN18, converted by group injected only */ +#define LL_ADC_AWD_CHANNEL_18_REG_INJ ((LL_ADC_CHANNEL_18 & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC external channel (channel connected to GPIO pin) ADCx_IN18, converted by either group regular or injected */ +#define LL_ADC_AWD_CH_VREFINT_REG ((LL_ADC_CHANNEL_VREFINT & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to VrefInt: Internal voltage reference, converted by group regular only */ +#define LL_ADC_AWD_CH_VREFINT_INJ ((LL_ADC_CHANNEL_VREFINT & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to VrefInt: Internal voltage reference, converted by group injected only */ +#define LL_ADC_AWD_CH_VREFINT_REG_INJ ((LL_ADC_CHANNEL_VREFINT & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to VrefInt: Internal voltage reference, converted by either group regular or injected */ +#define LL_ADC_AWD_CH_VBAT_REG ((LL_ADC_CHANNEL_VBAT & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Vbat/3: Vbat voltage through a divider ladder of factor 1/3 to have Vbat always below Vdda, converted by group regular only */ +#define LL_ADC_AWD_CH_VBAT_INJ ((LL_ADC_CHANNEL_VBAT & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Vbat/3: Vbat voltage through a divider ladder of factor 1/3 to have Vbat always below Vdda, converted by group injected only */ +#define LL_ADC_AWD_CH_VBAT_REG_INJ ((LL_ADC_CHANNEL_VBAT & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Vbat/3: Vbat voltage through a divider ladder of factor 1/3 to have Vbat always below Vdda */ +#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F405xx) || defined(STM32F407xx) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F415xx) || defined(STM32F417xx) +#define LL_ADC_AWD_CH_TEMPSENSOR_REG ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by group regular only */ +#define LL_ADC_AWD_CH_TEMPSENSOR_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by group injected only */ +#define LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by either group regular or injected */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F401xC || STM32F401xE || STM32F410xx */ +#if defined(STM32F411xE) || defined(STM32F412Cx) || defined(STM32F412Rx) || defined(STM32F412Vx) || defined(STM32F412Zx) || defined(STM32F413xx) || defined(STM32F423xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +#define LL_ADC_AWD_CH_TEMPSENSOR_REG ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by group regular only. This internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. */ +#define LL_ADC_AWD_CH_TEMPSENSOR_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by group injected only. This internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. */ +#define LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ ((LL_ADC_CHANNEL_TEMPSENSOR & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) /*!< ADC analog watchdog monitoring of ADC internal channel connected to Temperature sensor, converted by either group regular or injected. This internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. */ +#endif /* STM32F411xE || STM32F412Cx || STM32F412Rx || STM32F412Vx || STM32F412Zx || STM32F413xx || STM32F423xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_AWD_THRESHOLDS Analog watchdog - Thresholds + * @{ + */ +#define LL_ADC_AWD_THRESHOLD_HIGH (ADC_AWD_TR1_HIGH_REGOFFSET) /*!< ADC analog watchdog threshold high */ +#define LL_ADC_AWD_THRESHOLD_LOW (ADC_AWD_TR1_LOW_REGOFFSET) /*!< ADC analog watchdog threshold low */ +/** + * @} + */ + +#if defined(ADC_MULTIMODE_SUPPORT) +/** @defgroup ADC_LL_EC_MULTI_MODE Multimode - Mode + * @{ + */ +#define LL_ADC_MULTI_INDEPENDENT 0x00000000UL /*!< ADC dual mode disabled (ADC independent mode) */ +#define LL_ADC_MULTI_DUAL_REG_SIMULT ( ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 ) /*!< ADC dual mode enabled: group regular simultaneous */ +#define LL_ADC_MULTI_DUAL_REG_INTERL ( ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 | ADC_CCR_MULTI_0) /*!< ADC dual mode enabled: Combined group regular interleaved */ +#define LL_ADC_MULTI_DUAL_INJ_SIMULT ( ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0) /*!< ADC dual mode enabled: group injected simultaneous */ +#define LL_ADC_MULTI_DUAL_INJ_ALTERN (ADC_CCR_MULTI_3 | ADC_CCR_MULTI_0) /*!< ADC dual mode enabled: group injected alternate trigger. Works only with external triggers (not internal SW start) */ +#define LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM ( ADC_CCR_MULTI_0) /*!< ADC dual mode enabled: Combined group regular simultaneous + group injected simultaneous */ +#define LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT ( ADC_CCR_MULTI_1 ) /*!< ADC dual mode enabled: Combined group regular simultaneous + group injected alternate trigger */ +#define LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM ( ADC_CCR_MULTI_1 | ADC_CCR_MULTI_0) /*!< ADC dual mode enabled: Combined group regular interleaved + group injected simultaneous */ +#if defined(ADC3) +#define LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_SIM (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_0) /*!< ADC triple mode enabled: Combined group regular simultaneous + group injected simultaneous */ +#define LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_ALT (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_1 ) /*!< ADC triple mode enabled: Combined group regular simultaneous + group injected alternate trigger */ +#define LL_ADC_MULTI_TRIPLE_INJ_SIMULT (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_0) /*!< ADC triple mode enabled: group injected simultaneous */ +#define LL_ADC_MULTI_TRIPLE_REG_SIMULT (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 ) /*!< ADC triple mode enabled: group regular simultaneous */ +#define LL_ADC_MULTI_TRIPLE_REG_INTERL (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_2 | ADC_CCR_MULTI_1 | ADC_CCR_MULTI_0) /*!< ADC triple mode enabled: Combined group regular interleaved */ +#define LL_ADC_MULTI_TRIPLE_INJ_ALTERN (ADC_CCR_MULTI_4 | ADC_CCR_MULTI_0) /*!< ADC triple mode enabled: group injected alternate trigger. Works only with external triggers (not internal SW start) */ +#endif +/** + * @} + */ + +/** @defgroup ADC_LL_EC_MULTI_DMA_TRANSFER Multimode - DMA transfer + * @{ + */ +#define LL_ADC_MULTI_REG_DMA_EACH_ADC 0x00000000UL /*!< ADC multimode group regular conversions are transferred by DMA: each ADC uses its own DMA channel, with its individual DMA transfer settings */ +#define LL_ADC_MULTI_REG_DMA_LIMIT_1 ( ADC_CCR_DMA_0) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in limited mode (one shot mode): DMA transfer requests are stopped when number of DMA data transfers (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 1: 2 or 3 (dual or triple mode) half-words one by one, ADC1 then ADC2 then ADC3. */ +#define LL_ADC_MULTI_REG_DMA_LIMIT_2 ( ADC_CCR_DMA_1 ) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in limited mode (one shot mode): DMA transfer requests are stopped when number of DMA data transfers (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 2: 2 or 3 (dual or triple mode) half-words one by one, ADC2&1 then ADC1&3 then ADC3&2. */ +#define LL_ADC_MULTI_REG_DMA_LIMIT_3 ( ADC_CCR_DMA_1 | ADC_CCR_DMA_0) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in limited mode (one shot mode): DMA transfer requests are stopped when number of DMA data transfers (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 3: 2 or 3 (dual or triple mode) bytes one by one, ADC2&1 then ADC1&3 then ADC3&2. */ +#define LL_ADC_MULTI_REG_DMA_UNLMT_1 (ADC_CCR_DDS | ADC_CCR_DMA_0) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in unlimited mode: DMA transfer requests are unlimited, whatever number of DMA data transferred (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 1: 2 or 3 (dual or triple mode) half-words one by one, ADC1 then ADC2 then ADC3. */ +#define LL_ADC_MULTI_REG_DMA_UNLMT_2 (ADC_CCR_DDS | ADC_CCR_DMA_1 ) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in unlimited mode: DMA transfer requests are unlimited, whatever number of DMA data transferred (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 2: 2 or 3 (dual or triple mode) half-words by pairs, ADC2&1 then ADC1&3 then ADC3&2. */ +#define LL_ADC_MULTI_REG_DMA_UNLMT_3 (ADC_CCR_DDS | ADC_CCR_DMA_1 | ADC_CCR_DMA_0) /*!< ADC multimode group regular conversions are transferred by DMA, one DMA channel for all ADC instances (DMA of ADC master), in unlimited mode: DMA transfer requests are unlimited, whatever number of DMA data transferred (number of ADC conversions) is reached. This ADC mode is intended to be used with DMA mode non-circular. Setting of DMA mode 3: 2 or 3 (dual or triple mode) bytes one by one, ADC2&1 then ADC1&3 then ADC3&2. */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_MULTI_TWOSMP_DELAY Multimode - Delay between two sampling phases + * @{ + */ +#define LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES 0x00000000UL /*!< ADC multimode delay between two sampling phases: 5 ADC clock cycles*/ +#define LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES ( ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 6 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES ( ADC_CCR_DELAY_1 ) /*!< ADC multimode delay between two sampling phases: 7 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES ( ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 8 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES ( ADC_CCR_DELAY_2 ) /*!< ADC multimode delay between two sampling phases: 9 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES ( ADC_CCR_DELAY_2 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 10 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES ( ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1 ) /*!< ADC multimode delay between two sampling phases: 11 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES ( ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 12 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_13CYCLES (ADC_CCR_DELAY_3 ) /*!< ADC multimode delay between two sampling phases: 13 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_14CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 14 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_15CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_1 ) /*!< ADC multimode delay between two sampling phases: 15 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_16CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 16 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_17CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 ) /*!< ADC multimode delay between two sampling phases: 17 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_18CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 18 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_19CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1 ) /*!< ADC multimode delay between two sampling phases: 19 ADC clock cycles */ +#define LL_ADC_MULTI_TWOSMP_DELAY_20CYCLES (ADC_CCR_DELAY_3 | ADC_CCR_DELAY_2 | ADC_CCR_DELAY_1 | ADC_CCR_DELAY_0) /*!< ADC multimode delay between two sampling phases: 20 ADC clock cycles */ +/** + * @} + */ + +/** @defgroup ADC_LL_EC_MULTI_MASTER_SLAVE Multimode - ADC master or slave + * @{ + */ +#define LL_ADC_MULTI_MASTER ( ADC_CDR_RDATA_MST) /*!< In multimode, selection among several ADC instances: ADC master */ +#define LL_ADC_MULTI_SLAVE (ADC_CDR_RDATA_SLV ) /*!< In multimode, selection among several ADC instances: ADC slave */ +#define LL_ADC_MULTI_MASTER_SLAVE (ADC_CDR_RDATA_SLV | ADC_CDR_RDATA_MST) /*!< In multimode, selection among several ADC instances: both ADC master and ADC slave */ +/** + * @} + */ + +#endif /* ADC_MULTIMODE_SUPPORT */ + + +/** @defgroup ADC_LL_EC_HW_DELAYS Definitions of ADC hardware constraints delays + * @note Only ADC IP HW delays are defined in ADC LL driver driver, + * not timeout values. + * For details on delays values, refer to descriptions in source code + * above each literal definition. + * @{ + */ + +/* Note: Only ADC IP HW delays are defined in ADC LL driver driver, */ +/* not timeout values. */ +/* Timeout values for ADC operations are dependent to device clock */ +/* configuration (system clock versus ADC clock), */ +/* and therefore must be defined in user application. */ +/* Indications for estimation of ADC timeout delays, for this */ +/* STM32 series: */ +/* - ADC enable time: maximum delay is 2us */ +/* (refer to device datasheet, parameter "tSTAB") */ +/* - ADC conversion time: duration depending on ADC clock and ADC */ +/* configuration. */ +/* (refer to device reference manual, section "Timing") */ + +/* Delay for internal voltage reference stabilization time. */ +/* Delay set to maximum value (refer to device datasheet, */ +/* parameter "tSTART"). */ +/* Unit: us */ +#define LL_ADC_DELAY_VREFINT_STAB_US ( 10UL) /*!< Delay for internal voltage reference stabilization time */ + +/* Delay for temperature sensor stabilization time. */ +/* Literal set to maximum value (refer to device datasheet, */ +/* parameter "tSTART"). */ +/* Unit: us */ +#define LL_ADC_DELAY_TEMPSENSOR_STAB_US ( 10UL) /*!< Delay for internal voltage reference stabilization time */ + +/** + * @} + */ + +/** + * @} + */ + + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup ADC_LL_Exported_Macros ADC Exported Macros + * @{ + */ + +/** @defgroup ADC_LL_EM_WRITE_READ Common write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in ADC register + * @param __INSTANCE__ ADC Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_ADC_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in ADC register + * @param __INSTANCE__ ADC Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_ADC_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup ADC_LL_EM_HELPER_MACRO ADC helper macro + * @{ + */ + +/** + * @brief Helper macro to get ADC channel number in decimal format + * from literals LL_ADC_CHANNEL_x. + * @note Example: + * __LL_ADC_CHANNEL_TO_DECIMAL_NB(LL_ADC_CHANNEL_4) + * will return decimal number "4". + * @note The input can be a value from functions where a channel + * number is returned, either defined with number + * or with bitfield (only one bit must be set). + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval Value between Min_Data=0 and Max_Data=18 + */ +#define __LL_ADC_CHANNEL_TO_DECIMAL_NB(__CHANNEL__) \ + (((__CHANNEL__) & ADC_CHANNEL_ID_NUMBER_MASK) >> ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) + +/** + * @brief Helper macro to get ADC channel in literal format LL_ADC_CHANNEL_x + * from number in decimal format. + * @note Example: + * __LL_ADC_DECIMAL_NB_TO_CHANNEL(4) + * will return a data equivalent to "LL_ADC_CHANNEL_4". + * @param __DECIMAL_NB__ Value between Min_Data=0 and Max_Data=18 + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled.\n + * (1) For ADC channel read back from ADC register, + * comparison with internal channel parameter to be done + * using helper macro @ref __LL_ADC_CHANNEL_INTERNAL_TO_EXTERNAL(). + */ +#define __LL_ADC_DECIMAL_NB_TO_CHANNEL(__DECIMAL_NB__) \ + (((__DECIMAL_NB__) <= 9UL) \ + ? ( \ + ((__DECIMAL_NB__) << ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) | \ + (ADC_SMPR2_REGOFFSET | (((uint32_t) (3UL * (__DECIMAL_NB__))) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) \ + ) \ + : \ + ( \ + ((__DECIMAL_NB__) << ADC_CHANNEL_ID_NUMBER_BITOFFSET_POS) | \ + (ADC_SMPR1_REGOFFSET | (((uint32_t) (3UL * ((__DECIMAL_NB__) - 10UL))) << ADC_CHANNEL_SMPx_BITOFFSET_POS)) \ + ) \ + ) + +/** + * @brief Helper macro to determine whether the selected channel + * corresponds to literal definitions of driver. + * @note The different literal definitions of ADC channels are: + * - ADC internal channel: + * LL_ADC_CHANNEL_VREFINT, LL_ADC_CHANNEL_TEMPSENSOR, ... + * - ADC external channel (channel connected to a GPIO pin): + * LL_ADC_CHANNEL_1, LL_ADC_CHANNEL_2, ... + * @note The channel parameter must be a value defined from literal + * definition of a ADC internal channel (LL_ADC_CHANNEL_VREFINT, + * LL_ADC_CHANNEL_TEMPSENSOR, ...), + * ADC external channel (LL_ADC_CHANNEL_1, LL_ADC_CHANNEL_2, ...), + * must not be a value from functions where a channel number is + * returned from ADC registers, + * because internal and external channels share the same channel + * number in ADC registers. The differentiation is made only with + * parameters definitions of driver. + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval Value "0" if the channel corresponds to a parameter definition of a ADC external channel (channel connected to a GPIO pin). + * Value "1" if the channel corresponds to a parameter definition of a ADC internal channel. + */ +#define __LL_ADC_IS_CHANNEL_INTERNAL(__CHANNEL__) \ + (((__CHANNEL__) & ADC_CHANNEL_ID_INTERNAL_CH_MASK) != 0UL) + +/** + * @brief Helper macro to convert a channel defined from parameter + * definition of a ADC internal channel (LL_ADC_CHANNEL_VREFINT, + * LL_ADC_CHANNEL_TEMPSENSOR, ...), + * to its equivalent parameter definition of a ADC external channel + * (LL_ADC_CHANNEL_1, LL_ADC_CHANNEL_2, ...). + * @note The channel parameter can be, additionally to a value + * defined from parameter definition of a ADC internal channel + * (LL_ADC_CHANNEL_VREFINT, LL_ADC_CHANNEL_TEMPSENSOR, ...), + * a value defined from parameter definition of + * ADC external channel (LL_ADC_CHANNEL_1, LL_ADC_CHANNEL_2, ...) + * or a value from functions where a channel number is returned + * from ADC registers. + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + */ +#define __LL_ADC_CHANNEL_INTERNAL_TO_EXTERNAL(__CHANNEL__) \ + ((__CHANNEL__) & ~ADC_CHANNEL_ID_INTERNAL_CH_MASK) + +/** + * @brief Helper macro to determine whether the internal channel + * selected is available on the ADC instance selected. + * @note The channel parameter must be a value defined from parameter + * definition of a ADC internal channel (LL_ADC_CHANNEL_VREFINT, + * LL_ADC_CHANNEL_TEMPSENSOR, ...), + * must not be a value defined from parameter definition of + * ADC external channel (LL_ADC_CHANNEL_1, LL_ADC_CHANNEL_2, ...) + * or a value from functions where a channel number is + * returned from ADC registers, + * because internal and external channels share the same channel + * number in ADC registers. The differentiation is made only with + * parameters definitions of driver. + * @param __ADC_INSTANCE__ ADC instance + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1. + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval Value "0" if the internal channel selected is not available on the ADC instance selected. + * Value "1" if the internal channel selected is available on the ADC instance selected. + */ +#define __LL_ADC_IS_CHANNEL_INTERNAL_AVAILABLE(__ADC_INSTANCE__, __CHANNEL__) \ + ( \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VREFINT) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_TEMPSENSOR) || \ + ((__CHANNEL__) == LL_ADC_CHANNEL_VBAT) \ + ) +/** + * @brief Helper macro to define ADC analog watchdog parameter: + * define a single channel to monitor with analog watchdog + * from sequencer channel and groups definition. + * @note To be used with function @ref LL_ADC_SetAnalogWDMonitChannels(). + * Example: + * LL_ADC_SetAnalogWDMonitChannels( + * ADC1, LL_ADC_AWD1, + * __LL_ADC_ANALOGWD_CHANNEL_GROUP(LL_ADC_CHANNEL4, LL_ADC_GROUP_REGULAR)) + * @param __CHANNEL__ This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled.\n + * (1) For ADC channel read back from ADC register, + * comparison with internal channel parameter to be done + * using helper macro @ref __LL_ADC_CHANNEL_INTERNAL_TO_EXTERNAL(). + * @param __GROUP__ This parameter can be one of the following values: + * @arg @ref LL_ADC_GROUP_REGULAR + * @arg @ref LL_ADC_GROUP_INJECTED + * @arg @ref LL_ADC_GROUP_REGULAR_INJECTED + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_AWD_DISABLE + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG (1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_INJ (1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG_INJ (1) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG (1)(2) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_INJ (1)(2) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ (1)(2) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG (1) + * @arg @ref LL_ADC_AWD_CH_VBAT_INJ (1) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG_INJ (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + */ +#define __LL_ADC_ANALOGWD_CHANNEL_GROUP(__CHANNEL__, __GROUP__) \ + (((__GROUP__) == LL_ADC_GROUP_REGULAR) \ + ? (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) \ + : \ + ((__GROUP__) == LL_ADC_GROUP_INJECTED) \ + ? (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL) \ + : \ + (((__CHANNEL__) & ADC_CHANNEL_ID_MASK) | ADC_CR1_JAWDEN | ADC_CR1_AWDEN | ADC_CR1_AWDSGL) \ + ) + +/** + * @brief Helper macro to set the value of ADC analog watchdog threshold high + * or low in function of ADC resolution, when ADC resolution is + * different of 12 bits. + * @note To be used with function @ref LL_ADC_SetAnalogWDThresholds(). + * Example, with a ADC resolution of 8 bits, to set the value of + * analog watchdog threshold high (on 8 bits): + * LL_ADC_SetAnalogWDThresholds + * (< ADCx param >, + * __LL_ADC_ANALOGWD_SET_THRESHOLD_RESOLUTION(LL_ADC_RESOLUTION_8B, ) + * ); + * @param __ADC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @param __AWD_THRESHOLD__ Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +#define __LL_ADC_ANALOGWD_SET_THRESHOLD_RESOLUTION(__ADC_RESOLUTION__, __AWD_THRESHOLD__) \ + ((__AWD_THRESHOLD__) << ((__ADC_RESOLUTION__) >> (ADC_CR1_RES_BITOFFSET_POS - 1UL ))) + +/** + * @brief Helper macro to get the value of ADC analog watchdog threshold high + * or low in function of ADC resolution, when ADC resolution is + * different of 12 bits. + * @note To be used with function @ref LL_ADC_GetAnalogWDThresholds(). + * Example, with a ADC resolution of 8 bits, to get the value of + * analog watchdog threshold high (on 8 bits): + * < threshold_value_6_bits > = __LL_ADC_ANALOGWD_GET_THRESHOLD_RESOLUTION + * (LL_ADC_RESOLUTION_8B, + * LL_ADC_GetAnalogWDThresholds(, LL_ADC_AWD_THRESHOLD_HIGH) + * ); + * @param __ADC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @param __AWD_THRESHOLD_12_BITS__ Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +#define __LL_ADC_ANALOGWD_GET_THRESHOLD_RESOLUTION(__ADC_RESOLUTION__, __AWD_THRESHOLD_12_BITS__) \ + ((__AWD_THRESHOLD_12_BITS__) >> ((__ADC_RESOLUTION__) >> (ADC_CR1_RES_BITOFFSET_POS - 1UL ))) + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Helper macro to get the ADC multimode conversion data of ADC master + * or ADC slave from raw value with both ADC conversion data concatenated. + * @note This macro is intended to be used when multimode transfer by DMA + * is enabled: refer to function @ref LL_ADC_SetMultiDMATransfer(). + * In this case the transferred data need to processed with this macro + * to separate the conversion data of ADC master and ADC slave. + * @param __ADC_MULTI_MASTER_SLAVE__ This parameter can be one of the following values: + * @arg @ref LL_ADC_MULTI_MASTER + * @arg @ref LL_ADC_MULTI_SLAVE + * @param __ADC_MULTI_CONV_DATA__ Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +#define __LL_ADC_MULTI_CONV_DATA_MASTER_SLAVE(__ADC_MULTI_MASTER_SLAVE__, __ADC_MULTI_CONV_DATA__) \ + (((__ADC_MULTI_CONV_DATA__) >> POSITION_VAL((__ADC_MULTI_MASTER_SLAVE__))) & ADC_CDR_RDATA_MST) +#endif + +/** + * @brief Helper macro to select the ADC common instance + * to which is belonging the selected ADC instance. + * @note ADC common register instance can be used for: + * - Set parameters common to several ADC instances + * - Multimode (for devices with several ADC instances) + * Refer to functions having argument "ADCxy_COMMON" as parameter. + * @param __ADCx__ ADC instance + * @retval ADC common register instance + */ +#if defined(ADC1) && defined(ADC2) && defined(ADC3) +#define __LL_ADC_COMMON_INSTANCE(__ADCx__) \ + (ADC123_COMMON) +#elif defined(ADC1) && defined(ADC2) +#define __LL_ADC_COMMON_INSTANCE(__ADCx__) \ + (ADC12_COMMON) +#else +#define __LL_ADC_COMMON_INSTANCE(__ADCx__) \ + (ADC1_COMMON) +#endif + +/** + * @brief Helper macro to check if all ADC instances sharing the same + * ADC common instance are disabled. + * @note This check is required by functions with setting conditioned to + * ADC state: + * All ADC instances of the ADC common group must be disabled. + * Refer to functions having argument "ADCxy_COMMON" as parameter. + * @note On devices with only 1 ADC common instance, parameter of this macro + * is useless and can be ignored (parameter kept for compatibility + * with devices featuring several ADC common instances). + * @param __ADCXY_COMMON__ ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Value "0" if all ADC instances sharing the same ADC common instance + * are disabled. + * Value "1" if at least one ADC instance sharing the same ADC common instance + * is enabled. + */ +#if defined(ADC1) && defined(ADC2) && defined(ADC3) +#define __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__ADCXY_COMMON__) \ + (LL_ADC_IsEnabled(ADC1) | \ + LL_ADC_IsEnabled(ADC2) | \ + LL_ADC_IsEnabled(ADC3) ) +#elif defined(ADC1) && defined(ADC2) +#define __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__ADCXY_COMMON__) \ + (LL_ADC_IsEnabled(ADC1) | \ + LL_ADC_IsEnabled(ADC2) ) +#else +#define __LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(__ADCXY_COMMON__) \ + (LL_ADC_IsEnabled(ADC1)) +#endif + +/** + * @brief Helper macro to define the ADC conversion data full-scale digital + * value corresponding to the selected ADC resolution. + * @note ADC conversion data full-scale corresponds to voltage range + * determined by analog voltage references Vref+ and Vref- + * (refer to reference manual). + * @param __ADC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval ADC conversion data equivalent voltage value (unit: mVolt) + */ +#define __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__) \ + (0xFFFU >> ((__ADC_RESOLUTION__) >> (ADC_CR1_RES_BITOFFSET_POS - 1UL))) + +/** + * @brief Helper macro to convert the ADC conversion data from + * a resolution to another resolution. + * @param __DATA__ ADC conversion data to be converted + * @param __ADC_RESOLUTION_CURRENT__ Resolution of to the data to be converted + * This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @param __ADC_RESOLUTION_TARGET__ Resolution of the data after conversion + * This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval ADC conversion data to the requested resolution + */ +#define __LL_ADC_CONVERT_DATA_RESOLUTION(__DATA__, __ADC_RESOLUTION_CURRENT__, __ADC_RESOLUTION_TARGET__) \ + (((__DATA__) \ + << ((__ADC_RESOLUTION_CURRENT__) >> (ADC_CR1_RES_BITOFFSET_POS - 1UL))) \ + >> ((__ADC_RESOLUTION_TARGET__) >> (ADC_CR1_RES_BITOFFSET_POS - 1UL)) \ + ) + +/** + * @brief Helper macro to calculate the voltage (unit: mVolt) + * corresponding to a ADC conversion data (unit: digital value). + * @note Analog reference voltage (Vref+) must be either known from + * user board environment or can be calculated using ADC measurement + * and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE(). + * @param __VREFANALOG_VOLTAGE__ Analog reference voltage (unit mV) + * @param __ADC_DATA__ ADC conversion data (resolution 12 bits) + * (unit: digital value). + * @param __ADC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval ADC conversion data equivalent voltage value (unit: mVolt) + */ +#define __LL_ADC_CALC_DATA_TO_VOLTAGE(__VREFANALOG_VOLTAGE__,\ + __ADC_DATA__,\ + __ADC_RESOLUTION__) \ + ((__ADC_DATA__) * (__VREFANALOG_VOLTAGE__) \ + / __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__) \ + ) + +/** + * @brief Helper macro to calculate analog reference voltage (Vref+) + * (unit: mVolt) from ADC conversion data of internal voltage + * reference VrefInt. + * @note Computation is using VrefInt calibration value + * stored in system memory for each device during production. + * @note This voltage depends on user board environment: voltage level + * connected to pin Vref+. + * On devices with small package, the pin Vref+ is not present + * and internally bonded to pin Vdda. + * @note On this STM32 series, calibration data of internal voltage reference + * VrefInt corresponds to a resolution of 12 bits, + * this is the recommended ADC resolution to convert voltage of + * internal voltage reference VrefInt. + * Otherwise, this macro performs the processing to scale + * ADC conversion data to 12 bits. + * @param __VREFINT_ADC_DATA__ ADC conversion data (resolution 12 bits) + * of internal voltage reference VrefInt (unit: digital value). + * @param __ADC_RESOLUTION__ This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval Analog reference voltage (unit: mV) + */ +#define __LL_ADC_CALC_VREFANALOG_VOLTAGE(__VREFINT_ADC_DATA__,\ + __ADC_RESOLUTION__) \ + (((uint32_t)(*VREFINT_CAL_ADDR) * VREFINT_CAL_VREF) \ + / __LL_ADC_CONVERT_DATA_RESOLUTION((__VREFINT_ADC_DATA__), \ + (__ADC_RESOLUTION__), \ + LL_ADC_RESOLUTION_12B)) + +/* Note: On device STM32F4x9, calibration parameter TS_CAL2 is not available. */ +/* Therefore, helper macro __LL_ADC_CALC_TEMPERATURE() is not available.*/ +/* Use helper macro @ref __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(). */ +#if !defined(STM32F469) && !defined(STM32F479xx) && !defined(STM32F429xx) && !defined(STM32F439xx) +/** + * @brief Helper macro to calculate the temperature (unit: degree Celsius) + * from ADC conversion data of internal temperature sensor. + * @note Computation is using temperature sensor calibration values + * stored in system memory for each device during production. + * @note Calculation formula: + * Temperature = ((TS_ADC_DATA - TS_CAL1) + * * (TS_CAL2_TEMP - TS_CAL1_TEMP)) + * / (TS_CAL2 - TS_CAL1) + TS_CAL1_TEMP + * with TS_ADC_DATA = temperature sensor raw data measured by ADC + * Avg_Slope = (TS_CAL2 - TS_CAL1) + * / (TS_CAL2_TEMP - TS_CAL1_TEMP) + * TS_CAL1 = equivalent TS_ADC_DATA at temperature + * TEMP_DEGC_CAL1 (calibrated in factory) + * TS_CAL2 = equivalent TS_ADC_DATA at temperature + * TEMP_DEGC_CAL2 (calibrated in factory) + * Caution: Calculation relevancy under reserve that calibration + * parameters are correct (address and data). + * To calculate temperature using temperature sensor + * datasheet typical values (generic values less, therefore + * less accurate than calibrated values), + * use helper macro @ref __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(). + * @note As calculation input, the analog reference voltage (Vref+) must be + * defined as it impacts the ADC LSB equivalent voltage. + * @note Analog reference voltage (Vref+) must be either known from + * user board environment or can be calculated using ADC measurement + * and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE(). + * @note On this STM32 series, calibration data of temperature sensor + * corresponds to a resolution of 12 bits, + * this is the recommended ADC resolution to convert voltage of + * temperature sensor. + * Otherwise, this macro performs the processing to scale + * ADC conversion data to 12 bits. + * @param __VREFANALOG_VOLTAGE__ Analog reference voltage (unit mV) + * @param __TEMPSENSOR_ADC_DATA__ ADC conversion data of internal + * temperature sensor (unit: digital value). + * @param __ADC_RESOLUTION__ ADC resolution at which internal temperature + * sensor voltage has been measured. + * This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval Temperature (unit: degree Celsius) + */ +#define __LL_ADC_CALC_TEMPERATURE(__VREFANALOG_VOLTAGE__,\ + __TEMPSENSOR_ADC_DATA__,\ + __ADC_RESOLUTION__) \ + (((( ((int32_t)((__LL_ADC_CONVERT_DATA_RESOLUTION((__TEMPSENSOR_ADC_DATA__), \ + (__ADC_RESOLUTION__), \ + LL_ADC_RESOLUTION_12B) \ + * (__VREFANALOG_VOLTAGE__)) \ + / TEMPSENSOR_CAL_VREFANALOG) \ + - (int32_t) *TEMPSENSOR_CAL1_ADDR) \ + ) * (int32_t)(TEMPSENSOR_CAL2_TEMP - TEMPSENSOR_CAL1_TEMP) \ + ) / (int32_t)((int32_t)*TEMPSENSOR_CAL2_ADDR - (int32_t)*TEMPSENSOR_CAL1_ADDR) \ + ) + TEMPSENSOR_CAL1_TEMP \ + ) +#endif + +/** + * @brief Helper macro to calculate the temperature (unit: degree Celsius) + * from ADC conversion data of internal temperature sensor. + * @note Computation is using temperature sensor typical values + * (refer to device datasheet). + * @note Calculation formula: + * Temperature = (TS_TYP_CALx_VOLT(uV) - TS_ADC_DATA * Conversion_uV) + * / Avg_Slope + CALx_TEMP + * with TS_ADC_DATA = temperature sensor raw data measured by ADC + * (unit: digital value) + * Avg_Slope = temperature sensor slope + * (unit: uV/Degree Celsius) + * TS_TYP_CALx_VOLT = temperature sensor digital value at + * temperature CALx_TEMP (unit: mV) + * Caution: Calculation relevancy under reserve the temperature sensor + * of the current device has characteristics in line with + * datasheet typical values. + * If temperature sensor calibration values are available on + * on this device (presence of macro __LL_ADC_CALC_TEMPERATURE()), + * temperature calculation will be more accurate using + * helper macro @ref __LL_ADC_CALC_TEMPERATURE(). + * @note As calculation input, the analog reference voltage (Vref+) must be + * defined as it impacts the ADC LSB equivalent voltage. + * @note Analog reference voltage (Vref+) must be either known from + * user board environment or can be calculated using ADC measurement + * and ADC helper macro @ref __LL_ADC_CALC_VREFANALOG_VOLTAGE(). + * @note ADC measurement data must correspond to a resolution of 12bits + * (full scale digital value 4095). If not the case, the data must be + * preliminarily rescaled to an equivalent resolution of 12 bits. + * @param __TEMPSENSOR_TYP_AVGSLOPE__ Device datasheet data Temperature sensor slope typical value (unit uV/DegCelsius). + * On STM32F4, refer to device datasheet parameter "Avg_Slope". + * @param __TEMPSENSOR_TYP_CALX_V__ Device datasheet data Temperature sensor voltage typical value (at temperature and Vref+ defined in parameters below) (unit mV). + * On STM32F4, refer to device datasheet parameter "V25". + * @param __TEMPSENSOR_CALX_TEMP__ Device datasheet data Temperature at which temperature sensor voltage (see parameter above) is corresponding (unit mV) + * @param __VREFANALOG_VOLTAGE__ Analog voltage reference (Vref+) voltage (unit mV) + * @param __TEMPSENSOR_ADC_DATA__ ADC conversion data of internal temperature sensor (unit digital value). + * @param __ADC_RESOLUTION__ ADC resolution at which internal temperature sensor voltage has been measured. + * This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval Temperature (unit: degree Celsius) + */ +#define __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(__TEMPSENSOR_TYP_AVGSLOPE__,\ + __TEMPSENSOR_TYP_CALX_V__,\ + __TEMPSENSOR_CALX_TEMP__,\ + __VREFANALOG_VOLTAGE__,\ + __TEMPSENSOR_ADC_DATA__,\ + __ADC_RESOLUTION__) \ + ((( ( \ + (int32_t)(((__TEMPSENSOR_TYP_CALX_V__)) \ + * 1000) \ + - \ + (int32_t)((((__TEMPSENSOR_ADC_DATA__) * (__VREFANALOG_VOLTAGE__)) \ + / __LL_ADC_DIGITAL_SCALE(__ADC_RESOLUTION__)) \ + * 1000) \ + ) \ + ) / (__TEMPSENSOR_TYP_AVGSLOPE__) \ + ) + (__TEMPSENSOR_CALX_TEMP__) \ + ) + +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup ADC_LL_Exported_Functions ADC Exported Functions + * @{ + */ + +/** @defgroup ADC_LL_EF_DMA_Management ADC DMA management + * @{ + */ +/* Note: LL ADC functions to set DMA transfer are located into sections of */ +/* configuration of ADC instance, groups and multimode (if available): */ +/* @ref LL_ADC_REG_SetDMATransfer(), ... */ + +/** + * @brief Function to help to configure DMA transfer from ADC: retrieve the + * ADC register address from ADC instance and a list of ADC registers + * intended to be used (most commonly) with DMA transfer. + * @note These ADC registers are data registers: + * when ADC conversion data is available in ADC data registers, + * ADC generates a DMA transfer request. + * @note This macro is intended to be used with LL DMA driver, refer to + * function "LL_DMA_ConfigAddresses()". + * Example: + * LL_DMA_ConfigAddresses(DMA1, + * LL_DMA_CHANNEL_1, + * LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA), + * (uint32_t)&< array or variable >, + * LL_DMA_DIRECTION_PERIPH_TO_MEMORY); + * @note For devices with several ADC: in multimode, some devices + * use a different data register outside of ADC instance scope + * (common data register). This macro manages this register difference, + * only ADC instance has to be set as parameter. + * @rmtoll DR RDATA LL_ADC_DMA_GetRegAddr\n + * CDR RDATA_MST LL_ADC_DMA_GetRegAddr\n + * CDR RDATA_SLV LL_ADC_DMA_GetRegAddr + * @param ADCx ADC instance + * @param Register This parameter can be one of the following values: + * @arg @ref LL_ADC_DMA_REG_REGULAR_DATA + * @arg @ref LL_ADC_DMA_REG_REGULAR_DATA_MULTI (1) + * + * (1) Available on devices with several ADC instances. + * @retval ADC register address + */ +#if defined(ADC_MULTIMODE_SUPPORT) +__STATIC_INLINE uint32_t LL_ADC_DMA_GetRegAddr(ADC_TypeDef *ADCx, uint32_t Register) +{ + uint32_t data_reg_addr = 0UL; + + if (Register == LL_ADC_DMA_REG_REGULAR_DATA) + { + /* Retrieve address of register DR */ + data_reg_addr = (uint32_t) & (ADCx->DR); + } + else /* (Register == LL_ADC_DMA_REG_REGULAR_DATA_MULTI) */ + { + /* Retrieve address of register CDR */ + data_reg_addr = (uint32_t) & ((__LL_ADC_COMMON_INSTANCE(ADCx))->CDR); + } + + return data_reg_addr; +} +#else +__STATIC_INLINE uint32_t LL_ADC_DMA_GetRegAddr(ADC_TypeDef *ADCx, uint32_t Register) +{ + /* Prevent unused argument compilation warning */ + (void)Register; + + /* Retrieve address of register DR */ + return (uint32_t) & (ADCx->DR); +} +#endif + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Common Configuration of ADC hierarchical scope: common to several ADC instances + * @{ + */ + +/** + * @brief Set parameter common to several ADC: Clock source and prescaler. + * @rmtoll CCR ADCPRE LL_ADC_SetCommonClock + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param CommonClock This parameter can be one of the following values: + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV2 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV4 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV6 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV8 + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetCommonClock(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t CommonClock) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_ADCPRE, CommonClock); +} + +/** + * @brief Get parameter common to several ADC: Clock source and prescaler. + * @rmtoll CCR ADCPRE LL_ADC_GetCommonClock + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV2 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV4 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV6 + * @arg @ref LL_ADC_CLOCK_SYNC_PCLK_DIV8 + */ +__STATIC_INLINE uint32_t LL_ADC_GetCommonClock(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_ADCPRE)); +} + +/** + * @brief Set parameter common to several ADC: measurement path to internal + * channels (VrefInt, temperature sensor, ...). + * @note One or several values can be selected. + * Example: (LL_ADC_PATH_INTERNAL_VREFINT | + * LL_ADC_PATH_INTERNAL_TEMPSENSOR) + * @note Stabilization time of measurement path to internal channel: + * After enabling internal paths, before starting ADC conversion, + * a delay is required for internal voltage reference and + * temperature sensor stabilization time. + * Refer to device datasheet. + * Refer to literal @ref LL_ADC_DELAY_VREFINT_STAB_US. + * Refer to literal @ref LL_ADC_DELAY_TEMPSENSOR_STAB_US. + * @note ADC internal channel sampling time constraint: + * For ADC conversion of internal channels, + * a sampling time minimum value is required. + * Refer to device datasheet. + * @rmtoll CCR TSVREFE LL_ADC_SetCommonPathInternalCh\n + * CCR VBATE LL_ADC_SetCommonPathInternalCh + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param PathInternal This parameter can be a combination of the following values: + * @arg @ref LL_ADC_PATH_INTERNAL_NONE + * @arg @ref LL_ADC_PATH_INTERNAL_VREFINT + * @arg @ref LL_ADC_PATH_INTERNAL_TEMPSENSOR + * @arg @ref LL_ADC_PATH_INTERNAL_VBAT + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetCommonPathInternalCh(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t PathInternal) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_TSVREFE | ADC_CCR_VBATE, PathInternal); +} + +/** + * @brief Get parameter common to several ADC: measurement path to internal + * channels (VrefInt, temperature sensor, ...). + * @note One or several values can be selected. + * Example: (LL_ADC_PATH_INTERNAL_VREFINT | + * LL_ADC_PATH_INTERNAL_TEMPSENSOR) + * @rmtoll CCR TSVREFE LL_ADC_GetCommonPathInternalCh\n + * CCR VBATE LL_ADC_GetCommonPathInternalCh + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Returned value can be a combination of the following values: + * @arg @ref LL_ADC_PATH_INTERNAL_NONE + * @arg @ref LL_ADC_PATH_INTERNAL_VREFINT + * @arg @ref LL_ADC_PATH_INTERNAL_TEMPSENSOR + * @arg @ref LL_ADC_PATH_INTERNAL_VBAT + */ +__STATIC_INLINE uint32_t LL_ADC_GetCommonPathInternalCh(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_TSVREFE | ADC_CCR_VBATE)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Instance Configuration of ADC hierarchical scope: ADC instance + * @{ + */ + +/** + * @brief Set ADC resolution. + * Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CR1 RES LL_ADC_SetResolution + * @param ADCx ADC instance + * @param Resolution This parameter can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetResolution(ADC_TypeDef *ADCx, uint32_t Resolution) +{ + MODIFY_REG(ADCx->CR1, ADC_CR1_RES, Resolution); +} + +/** + * @brief Get ADC resolution. + * Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CR1 RES LL_ADC_GetResolution + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_RESOLUTION_12B + * @arg @ref LL_ADC_RESOLUTION_10B + * @arg @ref LL_ADC_RESOLUTION_8B + * @arg @ref LL_ADC_RESOLUTION_6B + */ +__STATIC_INLINE uint32_t LL_ADC_GetResolution(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, ADC_CR1_RES)); +} + +/** + * @brief Set ADC conversion data alignment. + * @note Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CR2 ALIGN LL_ADC_SetDataAlignment + * @param ADCx ADC instance + * @param DataAlignment This parameter can be one of the following values: + * @arg @ref LL_ADC_DATA_ALIGN_RIGHT + * @arg @ref LL_ADC_DATA_ALIGN_LEFT + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetDataAlignment(ADC_TypeDef *ADCx, uint32_t DataAlignment) +{ + MODIFY_REG(ADCx->CR2, ADC_CR2_ALIGN, DataAlignment); +} + +/** + * @brief Get ADC conversion data alignment. + * @note Refer to reference manual for alignments formats + * dependencies to ADC resolutions. + * @rmtoll CR2 ALIGN LL_ADC_SetDataAlignment + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_DATA_ALIGN_RIGHT + * @arg @ref LL_ADC_DATA_ALIGN_LEFT + */ +__STATIC_INLINE uint32_t LL_ADC_GetDataAlignment(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_ALIGN)); +} + +/** + * @brief Set ADC sequencers scan mode, for all ADC groups + * (group regular, group injected). + * @note According to sequencers scan mode : + * - If disabled: ADC conversion is performed in unitary conversion + * mode (one channel converted, that defined in rank 1). + * Configuration of sequencers of all ADC groups + * (sequencer scan length, ...) is discarded: equivalent to + * scan length of 1 rank. + * - If enabled: ADC conversions are performed in sequence conversions + * mode, according to configuration of sequencers of + * each ADC group (sequencer scan length, ...). + * Refer to function @ref LL_ADC_REG_SetSequencerLength() + * and to function @ref LL_ADC_INJ_SetSequencerLength(). + * @rmtoll CR1 SCAN LL_ADC_SetSequencersScanMode + * @param ADCx ADC instance + * @param ScanMode This parameter can be one of the following values: + * @arg @ref LL_ADC_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_SEQ_SCAN_ENABLE + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetSequencersScanMode(ADC_TypeDef *ADCx, uint32_t ScanMode) +{ + MODIFY_REG(ADCx->CR1, ADC_CR1_SCAN, ScanMode); +} + +/** + * @brief Get ADC sequencers scan mode, for all ADC groups + * (group regular, group injected). + * @note According to sequencers scan mode : + * - If disabled: ADC conversion is performed in unitary conversion + * mode (one channel converted, that defined in rank 1). + * Configuration of sequencers of all ADC groups + * (sequencer scan length, ...) is discarded: equivalent to + * scan length of 1 rank. + * - If enabled: ADC conversions are performed in sequence conversions + * mode, according to configuration of sequencers of + * each ADC group (sequencer scan length, ...). + * Refer to function @ref LL_ADC_REG_SetSequencerLength() + * and to function @ref LL_ADC_INJ_SetSequencerLength(). + * @rmtoll CR1 SCAN LL_ADC_GetSequencersScanMode + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_SEQ_SCAN_ENABLE + */ +__STATIC_INLINE uint32_t LL_ADC_GetSequencersScanMode(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, ADC_CR1_SCAN)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Group_Regular Configuration of ADC hierarchical scope: group regular + * @{ + */ + +/** + * @brief Set ADC group regular conversion trigger source: + * internal (SW start) or from external IP (timer event, + * external interrupt line). + * @note On this STM32 series, setting of external trigger edge is performed + * using function @ref LL_ADC_REG_StartConversionExtTrig(). + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR2 EXTSEL LL_ADC_REG_SetTriggerSource\n + * CR2 EXTEN LL_ADC_REG_SetTriggerSource + * @param ADCx ADC instance + * @param TriggerSource This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_TRIG_SOFTWARE + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_EXTI_LINE11 + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetTriggerSource(ADC_TypeDef *ADCx, uint32_t TriggerSource) +{ + /* Note: On this STM32 series, ADC group regular external trigger edge */ + /* is used to perform a ADC conversion start. */ + /* This function does not set external trigger edge. */ + /* This feature is set using function */ + /* @ref LL_ADC_REG_StartConversionExtTrig(). */ + MODIFY_REG(ADCx->CR2, ADC_CR2_EXTSEL, (TriggerSource & ADC_CR2_EXTSEL)); +} + +/** + * @brief Get ADC group regular conversion trigger source: + * internal (SW start) or from external IP (timer event, + * external interrupt line). + * @note To determine whether group regular trigger source is + * internal (SW start) or external, without detail + * of which peripheral is selected as external trigger, + * (equivalent to + * "if(LL_ADC_REG_GetTriggerSource(ADC1) == LL_ADC_REG_TRIG_SOFTWARE)") + * use function @ref LL_ADC_REG_IsTriggerSourceSWStart. + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR2 EXTSEL LL_ADC_REG_GetTriggerSource\n + * CR2 EXTEN LL_ADC_REG_GetTriggerSource + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_TRIG_SOFTWARE + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM1_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM3_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM4_CH4 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH2 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM5_CH3 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_CH1 + * @arg @ref LL_ADC_REG_TRIG_EXT_TIM8_TRGO + * @arg @ref LL_ADC_REG_TRIG_EXT_EXTI_LINE11 + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetTriggerSource(ADC_TypeDef *ADCx) +{ + uint32_t TriggerSource = READ_BIT(ADCx->CR2, ADC_CR2_EXTSEL | ADC_CR2_EXTEN); + + /* Value for shift of {0; 4; 8; 12} depending on value of bitfield */ + /* corresponding to ADC_CR2_EXTEN {0; 1; 2; 3}. */ + uint32_t ShiftExten = ((TriggerSource & ADC_CR2_EXTEN) >> (ADC_REG_TRIG_EXTEN_BITOFFSET_POS - 2UL)); + + /* Set bitfield corresponding to ADC_CR2_EXTEN and ADC_CR2_EXTSEL */ + /* to match with triggers literals definition. */ + return ((TriggerSource + & (ADC_REG_TRIG_SOURCE_MASK << ShiftExten) & ADC_CR2_EXTSEL) + | ((ADC_REG_TRIG_EDGE_MASK << ShiftExten) & ADC_CR2_EXTEN) + ); +} + +/** + * @brief Get ADC group regular conversion trigger source internal (SW start) + or external. + * @note In case of group regular trigger source set to external trigger, + * to determine which peripheral is selected as external trigger, + * use function @ref LL_ADC_REG_GetTriggerSource(). + * @rmtoll CR2 EXTEN LL_ADC_REG_IsTriggerSourceSWStart + * @param ADCx ADC instance + * @retval Value "0" if trigger source external trigger + * Value "1" if trigger source SW start. + */ +__STATIC_INLINE uint32_t LL_ADC_REG_IsTriggerSourceSWStart(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR2, ADC_CR2_EXTEN) == (LL_ADC_REG_TRIG_SOFTWARE & ADC_CR2_EXTEN)); +} + +/** + * @brief Get ADC group regular conversion trigger polarity. + * @note Applicable only for trigger source set to external trigger. + * @note On this STM32 series, setting of external trigger edge is performed + * using function @ref LL_ADC_REG_StartConversionExtTrig(). + * @rmtoll CR2 EXTEN LL_ADC_REG_GetTriggerEdge + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_TRIG_EXT_RISING + * @arg @ref LL_ADC_REG_TRIG_EXT_FALLING + * @arg @ref LL_ADC_REG_TRIG_EXT_RISINGFALLING + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetTriggerEdge(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_EXTEN)); +} + + +/** + * @brief Set ADC group regular sequencer length and scan direction. + * @note Description of ADC group regular sequencer features: + * - For devices with sequencer fully configurable + * (function "LL_ADC_REG_SetSequencerRanks()" available): + * sequencer length and each rank affectation to a channel + * are configurable. + * This function performs configuration of: + * - Sequence length: Number of ranks in the scan sequence. + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from rank 1 to rank n). + * Sequencer ranks are selected using + * function "LL_ADC_REG_SetSequencerRanks()". + * - For devices with sequencer not fully configurable + * (function "LL_ADC_REG_SetSequencerChannels()" available): + * sequencer length and each rank affectation to a channel + * are defined by channel number. + * This function performs configuration of: + * - Sequence length: Number of ranks in the scan sequence is + * defined by number of channels set in the sequence, + * rank of each channel is fixed by channel HW number. + * (channel 0 fixed on rank 0, channel 1 fixed on rank1, ...). + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from lowest channel number to + * highest channel number). + * Sequencer ranks are selected using + * function "LL_ADC_REG_SetSequencerChannels()". + * @note On this STM32 series, group regular sequencer configuration + * is conditioned to ADC instance sequencer mode. + * If ADC instance sequencer mode is disabled, sequencers of + * all groups (group regular, group injected) can be configured + * but their execution is disabled (limited to rank 1). + * Refer to function @ref LL_ADC_SetSequencersScanMode(). + * @note Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @rmtoll SQR1 L LL_ADC_REG_SetSequencerLength + * @param ADCx ADC instance + * @param SequencerNbRanks This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetSequencerLength(ADC_TypeDef *ADCx, uint32_t SequencerNbRanks) +{ + MODIFY_REG(ADCx->SQR1, ADC_SQR1_L, SequencerNbRanks); +} + +/** + * @brief Get ADC group regular sequencer length and scan direction. + * @note Description of ADC group regular sequencer features: + * - For devices with sequencer fully configurable + * (function "LL_ADC_REG_SetSequencerRanks()" available): + * sequencer length and each rank affectation to a channel + * are configurable. + * This function retrieves: + * - Sequence length: Number of ranks in the scan sequence. + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from rank 1 to rank n). + * Sequencer ranks are selected using + * function "LL_ADC_REG_SetSequencerRanks()". + * - For devices with sequencer not fully configurable + * (function "LL_ADC_REG_SetSequencerChannels()" available): + * sequencer length and each rank affectation to a channel + * are defined by channel number. + * This function retrieves: + * - Sequence length: Number of ranks in the scan sequence is + * defined by number of channels set in the sequence, + * rank of each channel is fixed by channel HW number. + * (channel 0 fixed on rank 0, channel 1 fixed on rank1, ...). + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from lowest channel number to + * highest channel number). + * Sequencer ranks are selected using + * function "LL_ADC_REG_SetSequencerChannels()". + * @note On this STM32 series, group regular sequencer configuration + * is conditioned to ADC instance sequencer mode. + * If ADC instance sequencer mode is disabled, sequencers of + * all groups (group regular, group injected) can be configured + * but their execution is disabled (limited to rank 1). + * Refer to function @ref LL_ADC_SetSequencersScanMode(). + * @note Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @rmtoll SQR1 L LL_ADC_REG_SetSequencerLength + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS + * @arg @ref LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetSequencerLength(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->SQR1, ADC_SQR1_L)); +} + +/** + * @brief Set ADC group regular sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @note It is not possible to enable both ADC group regular + * continuous mode and sequencer discontinuous mode. + * @note It is not possible to enable both ADC auto-injected mode + * and ADC group regular sequencer discontinuous mode. + * @rmtoll CR1 DISCEN LL_ADC_REG_SetSequencerDiscont\n + * CR1 DISCNUM LL_ADC_REG_SetSequencerDiscont + * @param ADCx ADC instance + * @param SeqDiscont This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_SEQ_DISCONT_DISABLE + * @arg @ref LL_ADC_REG_SEQ_DISCONT_1RANK + * @arg @ref LL_ADC_REG_SEQ_DISCONT_2RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_3RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_4RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_5RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_6RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_7RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_8RANKS + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetSequencerDiscont(ADC_TypeDef *ADCx, uint32_t SeqDiscont) +{ + MODIFY_REG(ADCx->CR1, ADC_CR1_DISCEN | ADC_CR1_DISCNUM, SeqDiscont); +} + +/** + * @brief Get ADC group regular sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @rmtoll CR1 DISCEN LL_ADC_REG_GetSequencerDiscont\n + * CR1 DISCNUM LL_ADC_REG_GetSequencerDiscont + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_SEQ_DISCONT_DISABLE + * @arg @ref LL_ADC_REG_SEQ_DISCONT_1RANK + * @arg @ref LL_ADC_REG_SEQ_DISCONT_2RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_3RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_4RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_5RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_6RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_7RANKS + * @arg @ref LL_ADC_REG_SEQ_DISCONT_8RANKS + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetSequencerDiscont(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, ADC_CR1_DISCEN | ADC_CR1_DISCNUM)); +} + +/** + * @brief Set ADC group regular sequence: channel on the selected + * scan sequence rank. + * @note This function performs configuration of: + * - Channels ordering into each rank of scan sequence: + * whatever channel can be placed into whatever rank. + * @note On this STM32 series, ADC group regular sequencer is + * fully configurable: sequencer length and each rank + * affectation to a channel are configurable. + * Refer to description of function @ref LL_ADC_REG_SetSequencerLength(). + * @note Depending on devices and packages, some channels may not be available. + * Refer to device datasheet for channels availability. + * @note On this STM32 series, to measure internal channels (VrefInt, + * TempSensor, ...), measurement paths to internal channels must be + * enabled separately. + * This can be done using function @ref LL_ADC_SetCommonPathInternalCh(). + * @rmtoll SQR3 SQ1 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ2 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ3 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ4 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ5 LL_ADC_REG_SetSequencerRanks\n + * SQR3 SQ6 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ7 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ8 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ9 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ10 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ11 LL_ADC_REG_SetSequencerRanks\n + * SQR2 SQ12 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ13 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ14 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ15 LL_ADC_REG_SetSequencerRanks\n + * SQR1 SQ16 LL_ADC_REG_SetSequencerRanks + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_RANK_1 + * @arg @ref LL_ADC_REG_RANK_2 + * @arg @ref LL_ADC_REG_RANK_3 + * @arg @ref LL_ADC_REG_RANK_4 + * @arg @ref LL_ADC_REG_RANK_5 + * @arg @ref LL_ADC_REG_RANK_6 + * @arg @ref LL_ADC_REG_RANK_7 + * @arg @ref LL_ADC_REG_RANK_8 + * @arg @ref LL_ADC_REG_RANK_9 + * @arg @ref LL_ADC_REG_RANK_10 + * @arg @ref LL_ADC_REG_RANK_11 + * @arg @ref LL_ADC_REG_RANK_12 + * @arg @ref LL_ADC_REG_RANK_13 + * @arg @ref LL_ADC_REG_RANK_14 + * @arg @ref LL_ADC_REG_RANK_15 + * @arg @ref LL_ADC_REG_RANK_16 + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetSequencerRanks(ADC_TypeDef *ADCx, uint32_t Rank, uint32_t Channel) +{ + /* Set bits with content of parameter "Channel" with bits position */ + /* in register and register position depending on parameter "Rank". */ + /* Parameters "Rank" and "Channel" are used with masks because containing */ + /* other bits reserved for other purpose. */ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SQR1, __ADC_MASK_SHIFT(Rank, ADC_REG_SQRX_REGOFFSET_MASK)); + + MODIFY_REG(*preg, + ADC_CHANNEL_ID_NUMBER_MASK << (Rank & ADC_REG_RANK_ID_SQRX_MASK), + (Channel & ADC_CHANNEL_ID_NUMBER_MASK) << (Rank & ADC_REG_RANK_ID_SQRX_MASK)); +} + +/** + * @brief Get ADC group regular sequence: channel on the selected + * scan sequence rank. + * @note On this STM32 series, ADC group regular sequencer is + * fully configurable: sequencer length and each rank + * affectation to a channel are configurable. + * Refer to description of function @ref LL_ADC_REG_SetSequencerLength(). + * @note Depending on devices and packages, some channels may not be available. + * Refer to device datasheet for channels availability. + * @note Usage of the returned channel number: + * - To reinject this channel into another function LL_ADC_xxx: + * the returned channel number is only partly formatted on definition + * of literals LL_ADC_CHANNEL_x. Therefore, it has to be compared + * with parts of literals LL_ADC_CHANNEL_x or using + * helper macro @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * Then the selected literal LL_ADC_CHANNEL_x can be used + * as parameter for another function. + * - To get the channel number in decimal format: + * process the returned value with the helper macro + * @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * @rmtoll SQR3 SQ1 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ2 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ3 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ4 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ5 LL_ADC_REG_GetSequencerRanks\n + * SQR3 SQ6 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ7 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ8 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ9 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ10 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ11 LL_ADC_REG_GetSequencerRanks\n + * SQR2 SQ12 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ13 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ14 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ15 LL_ADC_REG_GetSequencerRanks\n + * SQR1 SQ16 LL_ADC_REG_GetSequencerRanks + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_RANK_1 + * @arg @ref LL_ADC_REG_RANK_2 + * @arg @ref LL_ADC_REG_RANK_3 + * @arg @ref LL_ADC_REG_RANK_4 + * @arg @ref LL_ADC_REG_RANK_5 + * @arg @ref LL_ADC_REG_RANK_6 + * @arg @ref LL_ADC_REG_RANK_7 + * @arg @ref LL_ADC_REG_RANK_8 + * @arg @ref LL_ADC_REG_RANK_9 + * @arg @ref LL_ADC_REG_RANK_10 + * @arg @ref LL_ADC_REG_RANK_11 + * @arg @ref LL_ADC_REG_RANK_12 + * @arg @ref LL_ADC_REG_RANK_13 + * @arg @ref LL_ADC_REG_RANK_14 + * @arg @ref LL_ADC_REG_RANK_15 + * @arg @ref LL_ADC_REG_RANK_16 + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled.\n + * (1) For ADC channel read back from ADC register, + * comparison with internal channel parameter to be done + * using helper macro @ref __LL_ADC_CHANNEL_INTERNAL_TO_EXTERNAL(). + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetSequencerRanks(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SQR1, __ADC_MASK_SHIFT(Rank, ADC_REG_SQRX_REGOFFSET_MASK)); + + return (uint32_t)(READ_BIT(*preg, + ADC_CHANNEL_ID_NUMBER_MASK << (Rank & ADC_REG_RANK_ID_SQRX_MASK)) + >> (Rank & ADC_REG_RANK_ID_SQRX_MASK) + ); +} + +/** + * @brief Set ADC continuous conversion mode on ADC group regular. + * @note Description of ADC continuous conversion mode: + * - single mode: one conversion per trigger + * - continuous mode: after the first trigger, following + * conversions launched successively automatically. + * @note It is not possible to enable both ADC group regular + * continuous mode and sequencer discontinuous mode. + * @rmtoll CR2 CONT LL_ADC_REG_SetContinuousMode + * @param ADCx ADC instance + * @param Continuous This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_CONV_SINGLE + * @arg @ref LL_ADC_REG_CONV_CONTINUOUS + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetContinuousMode(ADC_TypeDef *ADCx, uint32_t Continuous) +{ + MODIFY_REG(ADCx->CR2, ADC_CR2_CONT, Continuous); +} + +/** + * @brief Get ADC continuous conversion mode on ADC group regular. + * @note Description of ADC continuous conversion mode: + * - single mode: one conversion per trigger + * - continuous mode: after the first trigger, following + * conversions launched successively automatically. + * @rmtoll CR2 CONT LL_ADC_REG_GetContinuousMode + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_CONV_SINGLE + * @arg @ref LL_ADC_REG_CONV_CONTINUOUS + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetContinuousMode(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_CONT)); +} + +/** + * @brief Set ADC group regular conversion data transfer: no transfer or + * transfer by DMA, and DMA requests mode. + * @note If transfer by DMA selected, specifies the DMA requests + * mode: + * - Limited mode (One shot mode): DMA transfer requests are stopped + * when number of DMA data transfers (number of + * ADC conversions) is reached. + * This ADC mode is intended to be used with DMA mode non-circular. + * - Unlimited mode: DMA transfer requests are unlimited, + * whatever number of DMA data transfers (number of + * ADC conversions). + * This ADC mode is intended to be used with DMA mode circular. + * @note If ADC DMA requests mode is set to unlimited and DMA is set to + * mode non-circular: + * when DMA transfers size will be reached, DMA will stop transfers of + * ADC conversions data ADC will raise an overrun error + * (overrun flag and interruption if enabled). + * @note For devices with several ADC instances: ADC multimode DMA + * settings are available using function @ref LL_ADC_SetMultiDMATransfer(). + * @note To configure DMA source address (peripheral address), + * use function @ref LL_ADC_DMA_GetRegAddr(). + * @rmtoll CR2 DMA LL_ADC_REG_SetDMATransfer\n + * CR2 DDS LL_ADC_REG_SetDMATransfer + * @param ADCx ADC instance + * @param DMATransfer This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_DMA_TRANSFER_NONE + * @arg @ref LL_ADC_REG_DMA_TRANSFER_LIMITED + * @arg @ref LL_ADC_REG_DMA_TRANSFER_UNLIMITED + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetDMATransfer(ADC_TypeDef *ADCx, uint32_t DMATransfer) +{ + MODIFY_REG(ADCx->CR2, ADC_CR2_DMA | ADC_CR2_DDS, DMATransfer); +} + +/** + * @brief Get ADC group regular conversion data transfer: no transfer or + * transfer by DMA, and DMA requests mode. + * @note If transfer by DMA selected, specifies the DMA requests + * mode: + * - Limited mode (One shot mode): DMA transfer requests are stopped + * when number of DMA data transfers (number of + * ADC conversions) is reached. + * This ADC mode is intended to be used with DMA mode non-circular. + * - Unlimited mode: DMA transfer requests are unlimited, + * whatever number of DMA data transfers (number of + * ADC conversions). + * This ADC mode is intended to be used with DMA mode circular. + * @note If ADC DMA requests mode is set to unlimited and DMA is set to + * mode non-circular: + * when DMA transfers size will be reached, DMA will stop transfers of + * ADC conversions data ADC will raise an overrun error + * (overrun flag and interruption if enabled). + * @note For devices with several ADC instances: ADC multimode DMA + * settings are available using function @ref LL_ADC_GetMultiDMATransfer(). + * @note To configure DMA source address (peripheral address), + * use function @ref LL_ADC_DMA_GetRegAddr(). + * @rmtoll CR2 DMA LL_ADC_REG_GetDMATransfer\n + * CR2 DDS LL_ADC_REG_GetDMATransfer + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_DMA_TRANSFER_NONE + * @arg @ref LL_ADC_REG_DMA_TRANSFER_LIMITED + * @arg @ref LL_ADC_REG_DMA_TRANSFER_UNLIMITED + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetDMATransfer(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_DMA | ADC_CR2_DDS)); +} + +/** + * @brief Specify which ADC flag between EOC (end of unitary conversion) + * or EOS (end of sequence conversions) is used to indicate + * the end of conversion. + * @note This feature is aimed to be set when using ADC with + * programming model by polling or interruption + * (programming model by DMA usually uses DMA interruptions + * to indicate end of conversion and data transfer). + * @note For ADC group injected, end of conversion (flag&IT) is raised + * only at the end of the sequence. + * @rmtoll CR2 EOCS LL_ADC_REG_SetFlagEndOfConversion + * @param ADCx ADC instance + * @param EocSelection This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV + * @arg @ref LL_ADC_REG_FLAG_EOC_UNITARY_CONV + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_SetFlagEndOfConversion(ADC_TypeDef *ADCx, uint32_t EocSelection) +{ + MODIFY_REG(ADCx->CR2, ADC_CR2_EOCS, EocSelection); +} + +/** + * @brief Get which ADC flag between EOC (end of unitary conversion) + * or EOS (end of sequence conversions) is used to indicate + * the end of conversion. + * @rmtoll CR2 EOCS LL_ADC_REG_GetFlagEndOfConversion + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV + * @arg @ref LL_ADC_REG_FLAG_EOC_UNITARY_CONV + */ +__STATIC_INLINE uint32_t LL_ADC_REG_GetFlagEndOfConversion(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_EOCS)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Group_Injected Configuration of ADC hierarchical scope: group injected + * @{ + */ + +/** + * @brief Set ADC group injected conversion trigger source: + * internal (SW start) or from external IP (timer event, + * external interrupt line). + * @note On this STM32 series, setting of external trigger edge is performed + * using function @ref LL_ADC_INJ_StartConversionExtTrig(). + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR2 JEXTSEL LL_ADC_INJ_SetTriggerSource\n + * CR2 JEXTEN LL_ADC_INJ_SetTriggerSource + * @param ADCx ADC instance + * @param TriggerSource This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_SOFTWARE + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM5_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM5_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetTriggerSource(ADC_TypeDef *ADCx, uint32_t TriggerSource) +{ + /* Note: On this STM32 series, ADC group injected external trigger edge */ + /* is used to perform a ADC conversion start. */ + /* This function does not set external trigger edge. */ + /* This feature is set using function */ + /* @ref LL_ADC_INJ_StartConversionExtTrig(). */ + MODIFY_REG(ADCx->CR2, ADC_CR2_JEXTSEL, (TriggerSource & ADC_CR2_JEXTSEL)); +} + +/** + * @brief Get ADC group injected conversion trigger source: + * internal (SW start) or from external IP (timer event, + * external interrupt line). + * @note To determine whether group injected trigger source is + * internal (SW start) or external, without detail + * of which peripheral is selected as external trigger, + * (equivalent to + * "if(LL_ADC_INJ_GetTriggerSource(ADC1) == LL_ADC_INJ_TRIG_SOFTWARE)") + * use function @ref LL_ADC_INJ_IsTriggerSourceSWStart. + * @note Availability of parameters of trigger sources from timer + * depends on timers availability on the selected device. + * @rmtoll CR2 JEXTSEL LL_ADC_INJ_GetTriggerSource\n + * CR2 JEXTEN LL_ADC_INJ_GetTriggerSource + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_SOFTWARE + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM1_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM2_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM3_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH1 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM4_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM5_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM5_TRGO + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH2 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH3 + * @arg @ref LL_ADC_INJ_TRIG_EXT_TIM8_CH4 + * @arg @ref LL_ADC_INJ_TRIG_EXT_EXTI_LINE15 + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetTriggerSource(ADC_TypeDef *ADCx) +{ + uint32_t TriggerSource = READ_BIT(ADCx->CR2, ADC_CR2_JEXTSEL | ADC_CR2_JEXTEN); + + /* Value for shift of {0; 4; 8; 12} depending on value of bitfield */ + /* corresponding to ADC_CR2_JEXTEN {0; 1; 2; 3}. */ + uint32_t ShiftExten = ((TriggerSource & ADC_CR2_JEXTEN) >> (ADC_INJ_TRIG_EXTEN_BITOFFSET_POS - 2UL)); + + /* Set bitfield corresponding to ADC_CR2_JEXTEN and ADC_CR2_JEXTSEL */ + /* to match with triggers literals definition. */ + return ((TriggerSource + & (ADC_INJ_TRIG_SOURCE_MASK << ShiftExten) & ADC_CR2_JEXTSEL) + | ((ADC_INJ_TRIG_EDGE_MASK << ShiftExten) & ADC_CR2_JEXTEN) + ); +} + +/** + * @brief Get ADC group injected conversion trigger source internal (SW start) + or external + * @note In case of group injected trigger source set to external trigger, + * to determine which peripheral is selected as external trigger, + * use function @ref LL_ADC_INJ_GetTriggerSource. + * @rmtoll CR2 JEXTEN LL_ADC_INJ_IsTriggerSourceSWStart + * @param ADCx ADC instance + * @retval Value "0" if trigger source external trigger + * Value "1" if trigger source SW start. + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_IsTriggerSourceSWStart(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR2, ADC_CR2_JEXTEN) == (LL_ADC_INJ_TRIG_SOFTWARE & ADC_CR2_JEXTEN)); +} + +/** + * @brief Get ADC group injected conversion trigger polarity. + * Applicable only for trigger source set to external trigger. + * @rmtoll CR2 JEXTEN LL_ADC_INJ_GetTriggerEdge + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_EXT_RISING + * @arg @ref LL_ADC_INJ_TRIG_EXT_FALLING + * @arg @ref LL_ADC_INJ_TRIG_EXT_RISINGFALLING + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetTriggerEdge(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR2, ADC_CR2_JEXTEN)); +} + +/** + * @brief Set ADC group injected sequencer length and scan direction. + * @note This function performs configuration of: + * - Sequence length: Number of ranks in the scan sequence. + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from rank 1 to rank n). + * @note On this STM32 series, group injected sequencer configuration + * is conditioned to ADC instance sequencer mode. + * If ADC instance sequencer mode is disabled, sequencers of + * all groups (group regular, group injected) can be configured + * but their execution is disabled (limited to rank 1). + * Refer to function @ref LL_ADC_SetSequencersScanMode(). + * @note Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @rmtoll JSQR JL LL_ADC_INJ_SetSequencerLength + * @param ADCx ADC instance + * @param SequencerNbRanks This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetSequencerLength(ADC_TypeDef *ADCx, uint32_t SequencerNbRanks) +{ + MODIFY_REG(ADCx->JSQR, ADC_JSQR_JL, SequencerNbRanks); +} + +/** + * @brief Get ADC group injected sequencer length and scan direction. + * @note This function retrieves: + * - Sequence length: Number of ranks in the scan sequence. + * - Sequence direction: Unless specified in parameters, sequencer + * scan direction is forward (from rank 1 to rank n). + * @note On this STM32 series, group injected sequencer configuration + * is conditioned to ADC instance sequencer mode. + * If ADC instance sequencer mode is disabled, sequencers of + * all groups (group regular, group injected) can be configured + * but their execution is disabled (limited to rank 1). + * Refer to function @ref LL_ADC_SetSequencersScanMode(). + * @note Sequencer disabled is equivalent to sequencer of 1 rank: + * ADC conversion on only 1 channel. + * @rmtoll JSQR JL LL_ADC_INJ_GetSequencerLength + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_SEQ_SCAN_DISABLE + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS + * @arg @ref LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetSequencerLength(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->JSQR, ADC_JSQR_JL)); +} + +/** + * @brief Set ADC group injected sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @note It is not possible to enable both ADC group injected + * auto-injected mode and sequencer discontinuous mode. + * @rmtoll CR1 DISCEN LL_ADC_INJ_SetSequencerDiscont + * @param ADCx ADC instance + * @param SeqDiscont This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_SEQ_DISCONT_DISABLE + * @arg @ref LL_ADC_INJ_SEQ_DISCONT_1RANK + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetSequencerDiscont(ADC_TypeDef *ADCx, uint32_t SeqDiscont) +{ + MODIFY_REG(ADCx->CR1, ADC_CR1_JDISCEN, SeqDiscont); +} + +/** + * @brief Get ADC group injected sequencer discontinuous mode: + * sequence subdivided and scan conversions interrupted every selected + * number of ranks. + * @rmtoll CR1 DISCEN LL_ADC_REG_GetSequencerDiscont + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_SEQ_DISCONT_DISABLE + * @arg @ref LL_ADC_INJ_SEQ_DISCONT_1RANK + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetSequencerDiscont(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, ADC_CR1_JDISCEN)); +} + +/** + * @brief Set ADC group injected sequence: channel on the selected + * sequence rank. + * @note Depending on devices and packages, some channels may not be available. + * Refer to device datasheet for channels availability. + * @note On this STM32 series, to measure internal channels (VrefInt, + * TempSensor, ...), measurement paths to internal channels must be + * enabled separately. + * This can be done using function @ref LL_ADC_SetCommonPathInternalCh(). + * @rmtoll JSQR JSQ1 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ2 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ3 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ4 LL_ADC_INJ_SetSequencerRanks + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetSequencerRanks(ADC_TypeDef *ADCx, uint32_t Rank, uint32_t Channel) +{ + /* Set bits with content of parameter "Channel" with bits position */ + /* in register depending on parameter "Rank". */ + /* Parameters "Rank" and "Channel" are used with masks because containing */ + /* other bits reserved for other purpose. */ + uint32_t tmpreg1 = (READ_BIT(ADCx->JSQR, ADC_JSQR_JL) >> ADC_JSQR_JL_Pos) + 1UL; + + MODIFY_REG(ADCx->JSQR, + ADC_CHANNEL_ID_NUMBER_MASK << (5UL * (uint8_t)(((Rank) + 3UL) - (tmpreg1))), + (Channel & ADC_CHANNEL_ID_NUMBER_MASK) << (5UL * (uint8_t)(((Rank) + 3UL) - (tmpreg1)))); +} + +/** + * @brief Get ADC group injected sequence: channel on the selected + * sequence rank. + * @note Depending on devices and packages, some channels may not be available. + * Refer to device datasheet for channels availability. + * @note Usage of the returned channel number: + * - To reinject this channel into another function LL_ADC_xxx: + * the returned channel number is only partly formatted on definition + * of literals LL_ADC_CHANNEL_x. Therefore, it has to be compared + * with parts of literals LL_ADC_CHANNEL_x or using + * helper macro @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * Then the selected literal LL_ADC_CHANNEL_x can be used + * as parameter for another function. + * - To get the channel number in decimal format: + * process the returned value with the helper macro + * @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * @rmtoll JSQR JSQ1 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ2 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ3 LL_ADC_INJ_SetSequencerRanks\n + * JSQR JSQ4 LL_ADC_INJ_SetSequencerRanks + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled.\n + * (1) For ADC channel read back from ADC register, + * comparison with internal channel parameter to be done + * using helper macro @ref __LL_ADC_CHANNEL_INTERNAL_TO_EXTERNAL(). + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetSequencerRanks(ADC_TypeDef *ADCx, uint32_t Rank) +{ + uint32_t tmpreg1 = (READ_BIT(ADCx->JSQR, ADC_JSQR_JL) >> ADC_JSQR_JL_Pos) + 1UL; + + return (uint32_t)(READ_BIT(ADCx->JSQR, + ADC_CHANNEL_ID_NUMBER_MASK << (5UL * (uint8_t)(((Rank) + 3UL) - (tmpreg1)))) + >> (5UL * (uint8_t)(((Rank) + 3UL) - (tmpreg1))) + ); +} + +/** + * @brief Set ADC group injected conversion trigger: + * independent or from ADC group regular. + * @note This mode can be used to extend number of data registers + * updated after one ADC conversion trigger and with data + * permanently kept (not erased by successive conversions of scan of + * ADC sequencer ranks), up to 5 data registers: + * 1 data register on ADC group regular, 4 data registers + * on ADC group injected. + * @note If ADC group injected injected trigger source is set to an + * external trigger, this feature must be must be set to + * independent trigger. + * ADC group injected automatic trigger is compliant only with + * group injected trigger source set to SW start, without any + * further action on ADC group injected conversion start or stop: + * in this case, ADC group injected is controlled only + * from ADC group regular. + * @note It is not possible to enable both ADC group injected + * auto-injected mode and sequencer discontinuous mode. + * @rmtoll CR1 JAUTO LL_ADC_INJ_SetTrigAuto + * @param ADCx ADC instance + * @param TrigAuto This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_INDEPENDENT + * @arg @ref LL_ADC_INJ_TRIG_FROM_GRP_REGULAR + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetTrigAuto(ADC_TypeDef *ADCx, uint32_t TrigAuto) +{ + MODIFY_REG(ADCx->CR1, ADC_CR1_JAUTO, TrigAuto); +} + +/** + * @brief Get ADC group injected conversion trigger: + * independent or from ADC group regular. + * @rmtoll CR1 JAUTO LL_ADC_INJ_GetTrigAuto + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_INDEPENDENT + * @arg @ref LL_ADC_INJ_TRIG_FROM_GRP_REGULAR + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetTrigAuto(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, ADC_CR1_JAUTO)); +} + +/** + * @brief Set ADC group injected offset. + * @note It sets: + * - ADC group injected rank to which the offset programmed + * will be applied + * - Offset level (offset to be subtracted from the raw + * converted data). + * Caution: Offset format is dependent to ADC resolution: + * offset has to be left-aligned on bit 11, the LSB (right bits) + * are set to 0. + * @note Offset cannot be enabled or disabled. + * To emulate offset disabled, set an offset value equal to 0. + * @rmtoll JOFR1 JOFFSET1 LL_ADC_INJ_SetOffset\n + * JOFR2 JOFFSET2 LL_ADC_INJ_SetOffset\n + * JOFR3 JOFFSET3 LL_ADC_INJ_SetOffset\n + * JOFR4 JOFFSET4 LL_ADC_INJ_SetOffset + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @param OffsetLevel Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_SetOffset(ADC_TypeDef *ADCx, uint32_t Rank, uint32_t OffsetLevel) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JOFR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JOFRX_REGOFFSET_MASK)); + + MODIFY_REG(*preg, + ADC_JOFR1_JOFFSET1, + OffsetLevel); +} + +/** + * @brief Get ADC group injected offset. + * @note It gives offset level (offset to be subtracted from the raw converted data). + * Caution: Offset format is dependent to ADC resolution: + * offset has to be left-aligned on bit 11, the LSB (right bits) + * are set to 0. + * @rmtoll JOFR1 JOFFSET1 LL_ADC_INJ_GetOffset\n + * JOFR2 JOFFSET2 LL_ADC_INJ_GetOffset\n + * JOFR3 JOFFSET3 LL_ADC_INJ_GetOffset\n + * JOFR4 JOFFSET4 LL_ADC_INJ_GetOffset + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_GetOffset(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JOFR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JOFRX_REGOFFSET_MASK)); + + return (uint32_t)(READ_BIT(*preg, + ADC_JOFR1_JOFFSET1) + ); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_Channels Configuration of ADC hierarchical scope: channels + * @{ + */ + +/** + * @brief Set sampling time of the selected ADC channel + * Unit: ADC clock cycles. + * @note On this device, sampling time is on channel scope: independently + * of channel mapped on ADC group regular or injected. + * @note In case of internal channel (VrefInt, TempSensor, ...) to be + * converted: + * sampling time constraints must be respected (sampling time can be + * adjusted in function of ADC clock frequency and sampling time + * setting). + * Refer to device datasheet for timings values (parameters TS_vrefint, + * TS_temp, ...). + * @note Conversion time is the addition of sampling time and processing time. + * Refer to reference manual for ADC processing time of + * this STM32 series. + * @note In case of ADC conversion of internal channel (VrefInt, + * temperature sensor, ...), a sampling time minimum value + * is required. + * Refer to device datasheet. + * @rmtoll SMPR1 SMP18 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP17 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP16 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP15 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP14 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP13 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP12 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP11 LL_ADC_SetChannelSamplingTime\n + * SMPR1 SMP10 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP9 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP8 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP7 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP6 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP5 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP4 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP3 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP2 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP1 LL_ADC_SetChannelSamplingTime\n + * SMPR2 SMP0 LL_ADC_SetChannelSamplingTime + * @param ADCx ADC instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @param SamplingTime This parameter can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_3CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_15CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_28CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_56CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_84CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_112CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_144CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_480CYCLES + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetChannelSamplingTime(ADC_TypeDef *ADCx, uint32_t Channel, uint32_t SamplingTime) +{ + /* Set bits with content of parameter "SamplingTime" with bits position */ + /* in register and register position depending on parameter "Channel". */ + /* Parameter "Channel" is used with masks because containing */ + /* other bits reserved for other purpose. */ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SMPR1, __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPRX_REGOFFSET_MASK)); + + MODIFY_REG(*preg, + ADC_SMPR2_SMP0 << __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPx_BITOFFSET_MASK), + SamplingTime << __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPx_BITOFFSET_MASK)); +} + +/** + * @brief Get sampling time of the selected ADC channel + * Unit: ADC clock cycles. + * @note On this device, sampling time is on channel scope: independently + * of channel mapped on ADC group regular or injected. + * @note Conversion time is the addition of sampling time and processing time. + * Refer to reference manual for ADC processing time of + * this STM32 series. + * @rmtoll SMPR1 SMP18 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP17 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP16 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP15 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP14 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP13 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP12 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP11 LL_ADC_GetChannelSamplingTime\n + * SMPR1 SMP10 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP9 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP8 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP7 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP6 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP5 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP4 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP3 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP2 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP1 LL_ADC_GetChannelSamplingTime\n + * SMPR2 SMP0 LL_ADC_GetChannelSamplingTime + * @param ADCx ADC instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_ADC_CHANNEL_0 + * @arg @ref LL_ADC_CHANNEL_1 + * @arg @ref LL_ADC_CHANNEL_2 + * @arg @ref LL_ADC_CHANNEL_3 + * @arg @ref LL_ADC_CHANNEL_4 + * @arg @ref LL_ADC_CHANNEL_5 + * @arg @ref LL_ADC_CHANNEL_6 + * @arg @ref LL_ADC_CHANNEL_7 + * @arg @ref LL_ADC_CHANNEL_8 + * @arg @ref LL_ADC_CHANNEL_9 + * @arg @ref LL_ADC_CHANNEL_10 + * @arg @ref LL_ADC_CHANNEL_11 + * @arg @ref LL_ADC_CHANNEL_12 + * @arg @ref LL_ADC_CHANNEL_13 + * @arg @ref LL_ADC_CHANNEL_14 + * @arg @ref LL_ADC_CHANNEL_15 + * @arg @ref LL_ADC_CHANNEL_16 + * @arg @ref LL_ADC_CHANNEL_17 + * @arg @ref LL_ADC_CHANNEL_18 + * @arg @ref LL_ADC_CHANNEL_VREFINT (1) + * @arg @ref LL_ADC_CHANNEL_TEMPSENSOR (1)(2) + * @arg @ref LL_ADC_CHANNEL_VBAT (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_SAMPLINGTIME_3CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_15CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_28CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_56CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_84CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_112CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_144CYCLES + * @arg @ref LL_ADC_SAMPLINGTIME_480CYCLES + */ +__STATIC_INLINE uint32_t LL_ADC_GetChannelSamplingTime(ADC_TypeDef *ADCx, uint32_t Channel) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->SMPR1, __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPRX_REGOFFSET_MASK)); + + return (uint32_t)(READ_BIT(*preg, + ADC_SMPR2_SMP0 << __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPx_BITOFFSET_MASK)) + >> __ADC_MASK_SHIFT(Channel, ADC_CHANNEL_SMPx_BITOFFSET_MASK) + ); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_AnalogWatchdog Configuration of ADC transversal scope: analog watchdog + * @{ + */ + +/** + * @brief Set ADC analog watchdog monitored channels: + * a single channel or all channels, + * on ADC groups regular and-or injected. + * @note Once monitored channels are selected, analog watchdog + * is enabled. + * @note In case of need to define a single channel to monitor + * with analog watchdog from sequencer channel definition, + * use helper macro @ref __LL_ADC_ANALOGWD_CHANNEL_GROUP(). + * @note On this STM32 series, there is only 1 kind of analog watchdog + * instance: + * - AWD standard (instance AWD1): + * - channels monitored: can monitor 1 channel or all channels. + * - groups monitored: ADC groups regular and-or injected. + * - resolution: resolution is not limited (corresponds to + * ADC resolution configured). + * @rmtoll CR1 AWD1CH LL_ADC_SetAnalogWDMonitChannels\n + * CR1 AWD1SGL LL_ADC_SetAnalogWDMonitChannels\n + * CR1 AWD1EN LL_ADC_SetAnalogWDMonitChannels + * @param ADCx ADC instance + * @param AWDChannelGroup This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD_DISABLE + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG (1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_INJ (1) + * @arg @ref LL_ADC_AWD_CH_VREFINT_REG_INJ (1) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG (1)(2) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_INJ (1)(2) + * @arg @ref LL_ADC_AWD_CH_TEMPSENSOR_REG_INJ (1)(2) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG (1) + * @arg @ref LL_ADC_AWD_CH_VBAT_INJ (1) + * @arg @ref LL_ADC_AWD_CH_VBAT_REG_INJ (1) + * + * (1) On STM32F4, parameter available only on ADC instance: ADC1.\n + * (2) On devices STM32F42x and STM32F43x, limitation: this internal channel is shared between temperature sensor and Vbat, only 1 measurement path must be enabled. + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetAnalogWDMonitChannels(ADC_TypeDef *ADCx, uint32_t AWDChannelGroup) +{ + MODIFY_REG(ADCx->CR1, + (ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL | ADC_CR1_AWDCH), + AWDChannelGroup); +} + +/** + * @brief Get ADC analog watchdog monitored channel. + * @note Usage of the returned channel number: + * - To reinject this channel into another function LL_ADC_xxx: + * the returned channel number is only partly formatted on definition + * of literals LL_ADC_CHANNEL_x. Therefore, it has to be compared + * with parts of literals LL_ADC_CHANNEL_x or using + * helper macro @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * Then the selected literal LL_ADC_CHANNEL_x can be used + * as parameter for another function. + * - To get the channel number in decimal format: + * process the returned value with the helper macro + * @ref __LL_ADC_CHANNEL_TO_DECIMAL_NB(). + * Applicable only when the analog watchdog is set to monitor + * one channel. + * @note On this STM32 series, there is only 1 kind of analog watchdog + * instance: + * - AWD standard (instance AWD1): + * - channels monitored: can monitor 1 channel or all channels. + * - groups monitored: ADC groups regular and-or injected. + * - resolution: resolution is not limited (corresponds to + * ADC resolution configured). + * @rmtoll CR1 AWD1CH LL_ADC_GetAnalogWDMonitChannels\n + * CR1 AWD1SGL LL_ADC_GetAnalogWDMonitChannels\n + * CR1 AWD1EN LL_ADC_GetAnalogWDMonitChannels + * @param ADCx ADC instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_AWD_DISABLE + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_INJ + * @arg @ref LL_ADC_AWD_ALL_CHANNELS_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG + * @arg @ref LL_ADC_AWD_CHANNEL_0_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_0_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG + * @arg @ref LL_ADC_AWD_CHANNEL_1_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_1_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG + * @arg @ref LL_ADC_AWD_CHANNEL_2_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_2_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG + * @arg @ref LL_ADC_AWD_CHANNEL_3_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_3_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG + * @arg @ref LL_ADC_AWD_CHANNEL_4_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_4_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG + * @arg @ref LL_ADC_AWD_CHANNEL_5_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_5_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG + * @arg @ref LL_ADC_AWD_CHANNEL_6_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_6_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG + * @arg @ref LL_ADC_AWD_CHANNEL_7_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_7_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG + * @arg @ref LL_ADC_AWD_CHANNEL_8_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_8_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG + * @arg @ref LL_ADC_AWD_CHANNEL_9_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_9_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG + * @arg @ref LL_ADC_AWD_CHANNEL_10_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_10_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG + * @arg @ref LL_ADC_AWD_CHANNEL_11_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_11_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG + * @arg @ref LL_ADC_AWD_CHANNEL_12_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_12_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG + * @arg @ref LL_ADC_AWD_CHANNEL_13_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_13_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG + * @arg @ref LL_ADC_AWD_CHANNEL_14_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_14_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG + * @arg @ref LL_ADC_AWD_CHANNEL_15_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_15_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG + * @arg @ref LL_ADC_AWD_CHANNEL_16_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_16_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG + * @arg @ref LL_ADC_AWD_CHANNEL_17_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_17_REG_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG + * @arg @ref LL_ADC_AWD_CHANNEL_18_INJ + * @arg @ref LL_ADC_AWD_CHANNEL_18_REG_INJ + */ +__STATIC_INLINE uint32_t LL_ADC_GetAnalogWDMonitChannels(ADC_TypeDef *ADCx) +{ + return (uint32_t)(READ_BIT(ADCx->CR1, (ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_AWDSGL | ADC_CR1_AWDCH))); +} + +/** + * @brief Set ADC analog watchdog threshold value of threshold + * high or low. + * @note In case of ADC resolution different of 12 bits, + * analog watchdog thresholds data require a specific shift. + * Use helper macro @ref __LL_ADC_ANALOGWD_SET_THRESHOLD_RESOLUTION(). + * @note On this STM32 series, there is only 1 kind of analog watchdog + * instance: + * - AWD standard (instance AWD1): + * - channels monitored: can monitor 1 channel or all channels. + * - groups monitored: ADC groups regular and-or injected. + * - resolution: resolution is not limited (corresponds to + * ADC resolution configured). + * @rmtoll HTR HT LL_ADC_SetAnalogWDThresholds\n + * LTR LT LL_ADC_SetAnalogWDThresholds + * @param ADCx ADC instance + * @param AWDThresholdsHighLow This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD_THRESHOLD_HIGH + * @arg @ref LL_ADC_AWD_THRESHOLD_LOW + * @param AWDThresholdValue Value between Min_Data=0x000 and Max_Data=0xFFF + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetAnalogWDThresholds(ADC_TypeDef *ADCx, uint32_t AWDThresholdsHighLow, uint32_t AWDThresholdValue) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->HTR, AWDThresholdsHighLow); + + MODIFY_REG(*preg, + ADC_HTR_HT, + AWDThresholdValue); +} + +/** + * @brief Get ADC analog watchdog threshold value of threshold high or + * threshold low. + * @note In case of ADC resolution different of 12 bits, + * analog watchdog thresholds data require a specific shift. + * Use helper macro @ref __LL_ADC_ANALOGWD_GET_THRESHOLD_RESOLUTION(). + * @rmtoll HTR HT LL_ADC_GetAnalogWDThresholds\n + * LTR LT LL_ADC_GetAnalogWDThresholds + * @param ADCx ADC instance + * @param AWDThresholdsHighLow This parameter can be one of the following values: + * @arg @ref LL_ADC_AWD_THRESHOLD_HIGH + * @arg @ref LL_ADC_AWD_THRESHOLD_LOW + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF +*/ +__STATIC_INLINE uint32_t LL_ADC_GetAnalogWDThresholds(ADC_TypeDef *ADCx, uint32_t AWDThresholdsHighLow) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->HTR, AWDThresholdsHighLow); + + return (uint32_t)(READ_BIT(*preg, ADC_HTR_HT)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Configuration_ADC_Multimode Configuration of ADC hierarchical scope: multimode + * @{ + */ + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Set ADC multimode configuration to operate in independent mode + * or multimode (for devices with several ADC instances). + * @note If multimode configuration: the selected ADC instance is + * either master or slave depending on hardware. + * Refer to reference manual. + * @rmtoll CCR MULTI LL_ADC_SetMultimode + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param Multimode This parameter can be one of the following values: + * @arg @ref LL_ADC_MULTI_INDEPENDENT + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIMULT + * @arg @ref LL_ADC_MULTI_DUAL_REG_INTERL + * @arg @ref LL_ADC_MULTI_DUAL_INJ_SIMULT + * @arg @ref LL_ADC_MULTI_DUAL_INJ_ALTERN + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT + * @arg @ref LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_SIM + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_ALT + * @arg @ref LL_ADC_MULTI_TRIPLE_INJ_SIMULT + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIMULT + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_INTERL + * @arg @ref LL_ADC_MULTI_TRIPLE_INJ_ALTERN + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetMultimode(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t Multimode) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_MULTI, Multimode); +} + +/** + * @brief Get ADC multimode configuration to operate in independent mode + * or multimode (for devices with several ADC instances). + * @note If multimode configuration: the selected ADC instance is + * either master or slave depending on hardware. + * Refer to reference manual. + * @rmtoll CCR MULTI LL_ADC_GetMultimode + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_MULTI_INDEPENDENT + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIMULT + * @arg @ref LL_ADC_MULTI_DUAL_REG_INTERL + * @arg @ref LL_ADC_MULTI_DUAL_INJ_SIMULT + * @arg @ref LL_ADC_MULTI_DUAL_INJ_ALTERN + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM + * @arg @ref LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT + * @arg @ref LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_SIM + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_ALT + * @arg @ref LL_ADC_MULTI_TRIPLE_INJ_SIMULT + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_SIMULT + * @arg @ref LL_ADC_MULTI_TRIPLE_REG_INTERL + * @arg @ref LL_ADC_MULTI_TRIPLE_INJ_ALTERN + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultimode(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_MULTI)); +} + +/** + * @brief Set ADC multimode conversion data transfer: no transfer + * or transfer by DMA. + * @note If ADC multimode transfer by DMA is not selected: + * each ADC uses its own DMA channel, with its individual + * DMA transfer settings. + * If ADC multimode transfer by DMA is selected: + * One DMA channel is used for both ADC (DMA of ADC master) + * Specifies the DMA requests mode: + * - Limited mode (One shot mode): DMA transfer requests are stopped + * when number of DMA data transfers (number of + * ADC conversions) is reached. + * This ADC mode is intended to be used with DMA mode non-circular. + * - Unlimited mode: DMA transfer requests are unlimited, + * whatever number of DMA data transfers (number of + * ADC conversions). + * This ADC mode is intended to be used with DMA mode circular. + * @note If ADC DMA requests mode is set to unlimited and DMA is set to + * mode non-circular: + * when DMA transfers size will be reached, DMA will stop transfers of + * ADC conversions data ADC will raise an overrun error + * (overrun flag and interruption if enabled). + * @note How to retrieve multimode conversion data: + * Whatever multimode transfer by DMA setting: using function + * @ref LL_ADC_REG_ReadMultiConversionData32(). + * If ADC multimode transfer by DMA is selected: conversion data + * is a raw data with ADC master and slave concatenated. + * A macro is available to get the conversion data of + * ADC master or ADC slave: see helper macro + * @ref __LL_ADC_MULTI_CONV_DATA_MASTER_SLAVE(). + * @rmtoll CCR MDMA LL_ADC_SetMultiDMATransfer\n + * CCR DDS LL_ADC_SetMultiDMATransfer + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param MultiDMATransfer This parameter can be one of the following values: + * @arg @ref LL_ADC_MULTI_REG_DMA_EACH_ADC + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_1 + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_2 + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_3 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_1 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_2 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_3 + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetMultiDMATransfer(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t MultiDMATransfer) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_DMA | ADC_CCR_DDS, MultiDMATransfer); +} + +/** + * @brief Get ADC multimode conversion data transfer: no transfer + * or transfer by DMA. + * @note If ADC multimode transfer by DMA is not selected: + * each ADC uses its own DMA channel, with its individual + * DMA transfer settings. + * If ADC multimode transfer by DMA is selected: + * One DMA channel is used for both ADC (DMA of ADC master) + * Specifies the DMA requests mode: + * - Limited mode (One shot mode): DMA transfer requests are stopped + * when number of DMA data transfers (number of + * ADC conversions) is reached. + * This ADC mode is intended to be used with DMA mode non-circular. + * - Unlimited mode: DMA transfer requests are unlimited, + * whatever number of DMA data transfers (number of + * ADC conversions). + * This ADC mode is intended to be used with DMA mode circular. + * @note If ADC DMA requests mode is set to unlimited and DMA is set to + * mode non-circular: + * when DMA transfers size will be reached, DMA will stop transfers of + * ADC conversions data ADC will raise an overrun error + * (overrun flag and interruption if enabled). + * @note How to retrieve multimode conversion data: + * Whatever multimode transfer by DMA setting: using function + * @ref LL_ADC_REG_ReadMultiConversionData32(). + * If ADC multimode transfer by DMA is selected: conversion data + * is a raw data with ADC master and slave concatenated. + * A macro is available to get the conversion data of + * ADC master or ADC slave: see helper macro + * @ref __LL_ADC_MULTI_CONV_DATA_MASTER_SLAVE(). + * @rmtoll CCR MDMA LL_ADC_GetMultiDMATransfer\n + * CCR DDS LL_ADC_GetMultiDMATransfer + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_MULTI_REG_DMA_EACH_ADC + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_1 + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_2 + * @arg @ref LL_ADC_MULTI_REG_DMA_LIMIT_3 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_1 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_2 + * @arg @ref LL_ADC_MULTI_REG_DMA_UNLMT_3 + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultiDMATransfer(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_DMA | ADC_CCR_DDS)); +} + +/** + * @brief Set ADC multimode delay between 2 sampling phases. + * @note The sampling delay range depends on ADC resolution: + * - ADC resolution 12 bits can have maximum delay of 12 cycles. + * - ADC resolution 10 bits can have maximum delay of 10 cycles. + * - ADC resolution 8 bits can have maximum delay of 8 cycles. + * - ADC resolution 6 bits can have maximum delay of 6 cycles. + * @rmtoll CCR DELAY LL_ADC_SetMultiTwoSamplingDelay + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param MultiTwoSamplingDelay This parameter can be one of the following values: + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_13CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_14CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_15CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_16CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_17CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_18CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_19CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_20CYCLES + * @retval None + */ +__STATIC_INLINE void LL_ADC_SetMultiTwoSamplingDelay(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t MultiTwoSamplingDelay) +{ + MODIFY_REG(ADCxy_COMMON->CCR, ADC_CCR_DELAY, MultiTwoSamplingDelay); +} + +/** + * @brief Get ADC multimode delay between 2 sampling phases. + * @rmtoll CCR DELAY LL_ADC_GetMultiTwoSamplingDelay + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval Returned value can be one of the following values: + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_13CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_14CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_15CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_16CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_17CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_18CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_19CYCLES + * @arg @ref LL_ADC_MULTI_TWOSMP_DELAY_20CYCLES + */ +__STATIC_INLINE uint32_t LL_ADC_GetMultiTwoSamplingDelay(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CCR, ADC_CCR_DELAY)); +} +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ +/** @defgroup ADC_LL_EF_Operation_ADC_Instance Operation on ADC hierarchical scope: ADC instance + * @{ + */ + +/** + * @brief Enable the selected ADC instance. + * @note On this STM32 series, after ADC enable, a delay for + * ADC internal analog stabilization is required before performing a + * ADC conversion start. + * Refer to device datasheet, parameter tSTAB. + * @rmtoll CR2 ADON LL_ADC_Enable + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_Enable(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR2, ADC_CR2_ADON); +} + +/** + * @brief Disable the selected ADC instance. + * @rmtoll CR2 ADON LL_ADC_Disable + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_Disable(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR2, ADC_CR2_ADON); +} + +/** + * @brief Get the selected ADC instance enable state. + * @rmtoll CR2 ADON LL_ADC_IsEnabled + * @param ADCx ADC instance + * @retval 0: ADC is disabled, 1: ADC is enabled. + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabled(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR2, ADC_CR2_ADON) == (ADC_CR2_ADON)); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Operation_ADC_Group_Regular Operation on ADC hierarchical scope: group regular + * @{ + */ + +/** + * @brief Start ADC group regular conversion. + * @note On this STM32 series, this function is relevant only for + * internal trigger (SW start), not for external trigger: + * - If ADC trigger has been set to software start, ADC conversion + * starts immediately. + * - If ADC trigger has been set to external trigger, ADC conversion + * start must be performed using function + * @ref LL_ADC_REG_StartConversionExtTrig(). + * (if external trigger edge would have been set during ADC other + * settings, ADC conversion would start at trigger event + * as soon as ADC is enabled). + * @rmtoll CR2 SWSTART LL_ADC_REG_StartConversionSWStart + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_StartConversionSWStart(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR2, ADC_CR2_SWSTART); +} + +/** + * @brief Start ADC group regular conversion from external trigger. + * @note ADC conversion will start at next trigger event (on the selected + * trigger edge) following the ADC start conversion command. + * @note On this STM32 series, this function is relevant for + * ADC conversion start from external trigger. + * If internal trigger (SW start) is needed, perform ADC conversion + * start using function @ref LL_ADC_REG_StartConversionSWStart(). + * @rmtoll CR2 EXTEN LL_ADC_REG_StartConversionExtTrig + * @param ExternalTriggerEdge This parameter can be one of the following values: + * @arg @ref LL_ADC_REG_TRIG_EXT_RISING + * @arg @ref LL_ADC_REG_TRIG_EXT_FALLING + * @arg @ref LL_ADC_REG_TRIG_EXT_RISINGFALLING + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_StartConversionExtTrig(ADC_TypeDef *ADCx, uint32_t ExternalTriggerEdge) +{ + SET_BIT(ADCx->CR2, ExternalTriggerEdge); +} + +/** + * @brief Stop ADC group regular conversion from external trigger. + * @note No more ADC conversion will start at next trigger event + * following the ADC stop conversion command. + * If a conversion is on-going, it will be completed. + * @note On this STM32 series, there is no specific command + * to stop a conversion on-going or to stop ADC converting + * in continuous mode. These actions can be performed + * using function @ref LL_ADC_Disable(). + * @rmtoll CR2 EXTEN LL_ADC_REG_StopConversionExtTrig + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_REG_StopConversionExtTrig(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR2, ADC_CR2_EXTEN); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * all ADC configurations: all ADC resolutions and + * all oversampling increased data width (for devices + * with feature oversampling). + * @rmtoll DR RDATA LL_ADC_REG_ReadConversionData32 + * @param ADCx ADC instance + * @retval Value between Min_Data=0x00000000 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_ADC_REG_ReadConversionData32(ADC_TypeDef *ADCx) +{ + return (uint16_t)(READ_BIT(ADCx->DR, ADC_DR_DATA)); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * ADC resolution 12 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_REG_ReadConversionData32. + * @rmtoll DR RDATA LL_ADC_REG_ReadConversionData12 + * @param ADCx ADC instance + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint16_t LL_ADC_REG_ReadConversionData12(ADC_TypeDef *ADCx) +{ + return (uint16_t)(READ_BIT(ADCx->DR, ADC_DR_DATA)); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * ADC resolution 10 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_REG_ReadConversionData32. + * @rmtoll DR RDATA LL_ADC_REG_ReadConversionData10 + * @param ADCx ADC instance + * @retval Value between Min_Data=0x000 and Max_Data=0x3FF + */ +__STATIC_INLINE uint16_t LL_ADC_REG_ReadConversionData10(ADC_TypeDef *ADCx) +{ + return (uint16_t)(READ_BIT(ADCx->DR, ADC_DR_DATA)); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * ADC resolution 8 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_REG_ReadConversionData32. + * @rmtoll DR RDATA LL_ADC_REG_ReadConversionData8 + * @param ADCx ADC instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_ADC_REG_ReadConversionData8(ADC_TypeDef *ADCx) +{ + return (uint8_t)(READ_BIT(ADCx->DR, ADC_DR_DATA)); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * ADC resolution 6 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_REG_ReadConversionData32. + * @rmtoll DR RDATA LL_ADC_REG_ReadConversionData6 + * @param ADCx ADC instance + * @retval Value between Min_Data=0x00 and Max_Data=0x3F + */ +__STATIC_INLINE uint8_t LL_ADC_REG_ReadConversionData6(ADC_TypeDef *ADCx) +{ + return (uint8_t)(READ_BIT(ADCx->DR, ADC_DR_DATA)); +} + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Get ADC multimode conversion data of ADC master, ADC slave + * or raw data with ADC master and slave concatenated. + * @note If raw data with ADC master and slave concatenated is retrieved, + * a macro is available to get the conversion data of + * ADC master or ADC slave: see helper macro + * @ref __LL_ADC_MULTI_CONV_DATA_MASTER_SLAVE(). + * (however this macro is mainly intended for multimode + * transfer by DMA, because this function can do the same + * by getting multimode conversion data of ADC master or ADC slave + * separately). + * @rmtoll CDR DATA1 LL_ADC_REG_ReadMultiConversionData32\n + * CDR DATA2 LL_ADC_REG_ReadMultiConversionData32 + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param ConversionData This parameter can be one of the following values: + * @arg @ref LL_ADC_MULTI_MASTER + * @arg @ref LL_ADC_MULTI_SLAVE + * @arg @ref LL_ADC_MULTI_MASTER_SLAVE + * @retval Value between Min_Data=0x00000000 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_ADC_REG_ReadMultiConversionData32(ADC_Common_TypeDef *ADCxy_COMMON, uint32_t ConversionData) +{ + return (uint32_t)(READ_BIT(ADCxy_COMMON->CDR, + ADC_DR_ADC2DATA) + >> POSITION_VAL(ConversionData) + ); +} +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_Operation_ADC_Group_Injected Operation on ADC hierarchical scope: group injected + * @{ + */ + +/** + * @brief Start ADC group injected conversion. + * @note On this STM32 series, this function is relevant only for + * internal trigger (SW start), not for external trigger: + * - If ADC trigger has been set to software start, ADC conversion + * starts immediately. + * - If ADC trigger has been set to external trigger, ADC conversion + * start must be performed using function + * @ref LL_ADC_INJ_StartConversionExtTrig(). + * (if external trigger edge would have been set during ADC other + * settings, ADC conversion would start at trigger event + * as soon as ADC is enabled). + * @rmtoll CR2 JSWSTART LL_ADC_INJ_StartConversionSWStart + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_StartConversionSWStart(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR2, ADC_CR2_JSWSTART); +} + +/** + * @brief Start ADC group injected conversion from external trigger. + * @note ADC conversion will start at next trigger event (on the selected + * trigger edge) following the ADC start conversion command. + * @note On this STM32 series, this function is relevant for + * ADC conversion start from external trigger. + * If internal trigger (SW start) is needed, perform ADC conversion + * start using function @ref LL_ADC_INJ_StartConversionSWStart(). + * @rmtoll CR2 JEXTEN LL_ADC_INJ_StartConversionExtTrig + * @param ExternalTriggerEdge This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_TRIG_EXT_RISING + * @arg @ref LL_ADC_INJ_TRIG_EXT_FALLING + * @arg @ref LL_ADC_INJ_TRIG_EXT_RISINGFALLING + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_StartConversionExtTrig(ADC_TypeDef *ADCx, uint32_t ExternalTriggerEdge) +{ + SET_BIT(ADCx->CR2, ExternalTriggerEdge); +} + +/** + * @brief Stop ADC group injected conversion from external trigger. + * @note No more ADC conversion will start at next trigger event + * following the ADC stop conversion command. + * If a conversion is on-going, it will be completed. + * @note On this STM32 series, there is no specific command + * to stop a conversion on-going or to stop ADC converting + * in continuous mode. These actions can be performed + * using function @ref LL_ADC_Disable(). + * @rmtoll CR2 JEXTEN LL_ADC_INJ_StopConversionExtTrig + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_INJ_StopConversionExtTrig(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR2, ADC_CR2_JEXTEN); +} + +/** + * @brief Get ADC group regular conversion data, range fit for + * all ADC configurations: all ADC resolutions and + * all oversampling increased data width (for devices + * with feature oversampling). + * @rmtoll JDR1 JDATA LL_ADC_INJ_ReadConversionData32\n + * JDR2 JDATA LL_ADC_INJ_ReadConversionData32\n + * JDR3 JDATA LL_ADC_INJ_ReadConversionData32\n + * JDR4 JDATA LL_ADC_INJ_ReadConversionData32 + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x00000000 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_ADC_INJ_ReadConversionData32(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JDRX_REGOFFSET_MASK)); + + return (uint32_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @brief Get ADC group injected conversion data, range fit for + * ADC resolution 12 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_INJ_ReadConversionData32. + * @rmtoll JDR1 JDATA LL_ADC_INJ_ReadConversionData12\n + * JDR2 JDATA LL_ADC_INJ_ReadConversionData12\n + * JDR3 JDATA LL_ADC_INJ_ReadConversionData12\n + * JDR4 JDATA LL_ADC_INJ_ReadConversionData12 + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x000 and Max_Data=0xFFF + */ +__STATIC_INLINE uint16_t LL_ADC_INJ_ReadConversionData12(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JDRX_REGOFFSET_MASK)); + + return (uint16_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @brief Get ADC group injected conversion data, range fit for + * ADC resolution 10 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_INJ_ReadConversionData32. + * @rmtoll JDR1 JDATA LL_ADC_INJ_ReadConversionData10\n + * JDR2 JDATA LL_ADC_INJ_ReadConversionData10\n + * JDR3 JDATA LL_ADC_INJ_ReadConversionData10\n + * JDR4 JDATA LL_ADC_INJ_ReadConversionData10 + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x000 and Max_Data=0x3FF + */ +__STATIC_INLINE uint16_t LL_ADC_INJ_ReadConversionData10(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JDRX_REGOFFSET_MASK)); + + return (uint16_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @brief Get ADC group injected conversion data, range fit for + * ADC resolution 8 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_INJ_ReadConversionData32. + * @rmtoll JDR1 JDATA LL_ADC_INJ_ReadConversionData8\n + * JDR2 JDATA LL_ADC_INJ_ReadConversionData8\n + * JDR3 JDATA LL_ADC_INJ_ReadConversionData8\n + * JDR4 JDATA LL_ADC_INJ_ReadConversionData8 + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_ADC_INJ_ReadConversionData8(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JDRX_REGOFFSET_MASK)); + + return (uint8_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @brief Get ADC group injected conversion data, range fit for + * ADC resolution 6 bits. + * @note For devices with feature oversampling: Oversampling + * can increase data width, function for extended range + * may be needed: @ref LL_ADC_INJ_ReadConversionData32. + * @rmtoll JDR1 JDATA LL_ADC_INJ_ReadConversionData6\n + * JDR2 JDATA LL_ADC_INJ_ReadConversionData6\n + * JDR3 JDATA LL_ADC_INJ_ReadConversionData6\n + * JDR4 JDATA LL_ADC_INJ_ReadConversionData6 + * @param ADCx ADC instance + * @param Rank This parameter can be one of the following values: + * @arg @ref LL_ADC_INJ_RANK_1 + * @arg @ref LL_ADC_INJ_RANK_2 + * @arg @ref LL_ADC_INJ_RANK_3 + * @arg @ref LL_ADC_INJ_RANK_4 + * @retval Value between Min_Data=0x00 and Max_Data=0x3F + */ +__STATIC_INLINE uint8_t LL_ADC_INJ_ReadConversionData6(ADC_TypeDef *ADCx, uint32_t Rank) +{ + __IO uint32_t *preg = __ADC_PTR_REG_OFFSET(ADCx->JDR1, __ADC_MASK_SHIFT(Rank, ADC_INJ_JDRX_REGOFFSET_MASK)); + + return (uint8_t)(READ_BIT(*preg, + ADC_JDR1_JDATA) + ); +} + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_FLAG_Management ADC flag management + * @{ + */ + +/** + * @brief Get flag ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll SR EOC LL_ADC_IsActiveFlag_EOCS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_EOCS(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->SR, LL_ADC_FLAG_EOCS) == (LL_ADC_FLAG_EOCS)); +} + +/** + * @brief Get flag ADC group regular overrun. + * @rmtoll SR OVR LL_ADC_IsActiveFlag_OVR + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_OVR(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->SR, LL_ADC_FLAG_OVR) == (LL_ADC_FLAG_OVR)); +} + + +/** + * @brief Get flag ADC group injected end of sequence conversions. + * @rmtoll SR JEOC LL_ADC_IsActiveFlag_JEOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_JEOS(ADC_TypeDef *ADCx) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + return (READ_BIT(ADCx->SR, LL_ADC_FLAG_JEOS) == (LL_ADC_FLAG_JEOS)); +} + +/** + * @brief Get flag ADC analog watchdog 1 flag + * @rmtoll SR AWD LL_ADC_IsActiveFlag_AWD1 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_AWD1(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->SR, LL_ADC_FLAG_AWD1) == (LL_ADC_FLAG_AWD1)); +} + +/** + * @brief Clear flag ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll SR EOC LL_ADC_ClearFlag_EOCS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_EOCS(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->SR, ~LL_ADC_FLAG_EOCS); +} + +/** + * @brief Clear flag ADC group regular overrun. + * @rmtoll SR OVR LL_ADC_ClearFlag_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_OVR(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->SR, ~LL_ADC_FLAG_OVR); +} + + +/** + * @brief Clear flag ADC group injected end of sequence conversions. + * @rmtoll SR JEOC LL_ADC_ClearFlag_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_JEOS(ADC_TypeDef *ADCx) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + WRITE_REG(ADCx->SR, ~LL_ADC_FLAG_JEOS); +} + +/** + * @brief Clear flag ADC analog watchdog 1. + * @rmtoll SR AWD LL_ADC_ClearFlag_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_ClearFlag_AWD1(ADC_TypeDef *ADCx) +{ + WRITE_REG(ADCx->SR, ~LL_ADC_FLAG_AWD1); +} + +#if defined(ADC_MULTIMODE_SUPPORT) +/** + * @brief Get flag multimode ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration, of the ADC master. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll CSR EOC1 LL_ADC_IsActiveFlag_MST_EOCS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_MST_EOCS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOCS_MST) == (LL_ADC_FLAG_EOCS_MST)); +} + +/** + * @brief Get flag multimode ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration, of the ADC slave 1. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll CSR EOC2 LL_ADC_IsActiveFlag_SLV1_EOCS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV1_EOCS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOCS_SLV1) == (LL_ADC_FLAG_EOCS_SLV1)); +} + +/** + * @brief Get flag multimode ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration, of the ADC slave 2. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll CSR EOC3 LL_ADC_IsActiveFlag_SLV2_EOCS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV2_EOCS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_EOCS_SLV2) == (LL_ADC_FLAG_EOCS_SLV2)); +} +/** + * @brief Get flag multimode ADC group regular overrun of the ADC master. + * @rmtoll CSR OVR1 LL_ADC_IsActiveFlag_MST_OVR + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_MST_OVR(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_OVR_MST) == (LL_ADC_FLAG_OVR_MST)); +} + +/** + * @brief Get flag multimode ADC group regular overrun of the ADC slave 1. + * @rmtoll CSR OVR2 LL_ADC_IsActiveFlag_SLV1_OVR + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV1_OVR(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_OVR_SLV1) == (LL_ADC_FLAG_OVR_SLV1)); +} + +/** + * @brief Get flag multimode ADC group regular overrun of the ADC slave 2. + * @rmtoll CSR OVR3 LL_ADC_IsActiveFlag_SLV2_OVR + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV2_OVR(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_OVR_SLV2) == (LL_ADC_FLAG_OVR_SLV2)); +} + + +/** + * @brief Get flag multimode ADC group injected end of sequence conversions of the ADC master. + * @rmtoll CSR JEOC LL_ADC_IsActiveFlag_MST_JEOS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_MST_JEOS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + return (READ_BIT(ADCxy_COMMON->CSR, ADC_CSR_JEOC1) == (ADC_CSR_JEOC1)); +} + +/** + * @brief Get flag multimode ADC group injected end of sequence conversions of the ADC slave 1. + * @rmtoll CSR JEOC2 LL_ADC_IsActiveFlag_SLV1_JEOS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV1_JEOS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + return (READ_BIT(ADCxy_COMMON->CSR, ADC_CSR_JEOC2) == (ADC_CSR_JEOC2)); +} + +/** + * @brief Get flag multimode ADC group injected end of sequence conversions of the ADC slave 2. + * @rmtoll CSR JEOC3 LL_ADC_IsActiveFlag_SLV2_JEOS + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV2_JEOS(ADC_Common_TypeDef *ADCxy_COMMON) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + return (READ_BIT(ADCxy_COMMON->CSR, ADC_CSR_JEOC3) == (ADC_CSR_JEOC3)); +} + +/** + * @brief Get flag multimode ADC analog watchdog 1 of the ADC master. + * @rmtoll CSR AWD1 LL_ADC_IsActiveFlag_MST_AWD1 + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_MST_AWD1(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD1_MST) == (LL_ADC_FLAG_AWD1_MST)); +} + +/** + * @brief Get flag multimode analog watchdog 1 of the ADC slave 1. + * @rmtoll CSR AWD2 LL_ADC_IsActiveFlag_SLV1_AWD1 + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV1_AWD1(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD1_SLV1) == (LL_ADC_FLAG_AWD1_SLV1)); +} + +/** + * @brief Get flag multimode analog watchdog 1 of the ADC slave 2. + * @rmtoll CSR AWD3 LL_ADC_IsActiveFlag_SLV2_AWD1 + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsActiveFlag_SLV2_AWD1(ADC_Common_TypeDef *ADCxy_COMMON) +{ + return (READ_BIT(ADCxy_COMMON->CSR, LL_ADC_FLAG_AWD1_SLV2) == (LL_ADC_FLAG_AWD1_SLV2)); +} + +#endif /* ADC_MULTIMODE_SUPPORT */ + +/** + * @} + */ + +/** @defgroup ADC_LL_EF_IT_Management ADC IT management + * @{ + */ + +/** + * @brief Enable interruption ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll CR1 EOCIE LL_ADC_EnableIT_EOCS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_EOCS(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR1, LL_ADC_IT_EOCS); +} + +/** + * @brief Enable ADC group regular interruption overrun. + * @rmtoll CR1 OVRIE LL_ADC_EnableIT_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_OVR(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR1, LL_ADC_IT_OVR); +} + + +/** + * @brief Enable interruption ADC group injected end of sequence conversions. + * @rmtoll CR1 JEOCIE LL_ADC_EnableIT_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_JEOS(ADC_TypeDef *ADCx) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + SET_BIT(ADCx->CR1, LL_ADC_IT_JEOS); +} + +/** + * @brief Enable interruption ADC analog watchdog 1. + * @rmtoll CR1 AWDIE LL_ADC_EnableIT_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_EnableIT_AWD1(ADC_TypeDef *ADCx) +{ + SET_BIT(ADCx->CR1, LL_ADC_IT_AWD1); +} + +/** + * @brief Disable interruption ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * @rmtoll CR1 EOCIE LL_ADC_DisableIT_EOCS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_EOCS(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR1, LL_ADC_IT_EOCS); +} + +/** + * @brief Disable interruption ADC group regular overrun. + * @rmtoll CR1 OVRIE LL_ADC_DisableIT_OVR + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_OVR(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR1, LL_ADC_IT_OVR); +} + + +/** + * @brief Disable interruption ADC group injected end of sequence conversions. + * @rmtoll CR1 JEOCIE LL_ADC_EnableIT_JEOS + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_JEOS(ADC_TypeDef *ADCx) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + CLEAR_BIT(ADCx->CR1, LL_ADC_IT_JEOS); +} + +/** + * @brief Disable interruption ADC analog watchdog 1. + * @rmtoll CR1 AWDIE LL_ADC_EnableIT_AWD1 + * @param ADCx ADC instance + * @retval None + */ +__STATIC_INLINE void LL_ADC_DisableIT_AWD1(ADC_TypeDef *ADCx) +{ + CLEAR_BIT(ADCx->CR1, LL_ADC_IT_AWD1); +} + +/** + * @brief Get state of interruption ADC group regular end of unitary conversion + * or end of sequence conversions, depending on + * ADC configuration. + * @note To configure flag of end of conversion, + * use function @ref LL_ADC_REG_SetFlagEndOfConversion(). + * (0: interrupt disabled, 1: interrupt enabled) + * @rmtoll CR1 EOCIE LL_ADC_IsEnabledIT_EOCS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_EOCS(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR1, LL_ADC_IT_EOCS) == (LL_ADC_IT_EOCS)); +} + +/** + * @brief Get state of interruption ADC group regular overrun + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll CR1 OVRIE LL_ADC_IsEnabledIT_OVR + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_OVR(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR1, LL_ADC_IT_OVR) == (LL_ADC_IT_OVR)); +} + + +/** + * @brief Get state of interruption ADC group injected end of sequence conversions + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll CR1 JEOCIE LL_ADC_EnableIT_JEOS + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_JEOS(ADC_TypeDef *ADCx) +{ + /* Note: on this STM32 series, there is no flag ADC group injected */ + /* end of unitary conversion. */ + /* Flag noted as "JEOC" is corresponding to flag "JEOS" */ + /* in other STM32 families). */ + return (READ_BIT(ADCx->CR1, LL_ADC_IT_JEOS) == (LL_ADC_IT_JEOS)); +} + +/** + * @brief Get state of interruption ADC analog watchdog 1 + * (0: interrupt disabled, 1: interrupt enabled). + * @rmtoll CR1 AWDIE LL_ADC_EnableIT_AWD1 + * @param ADCx ADC instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_ADC_IsEnabledIT_AWD1(ADC_TypeDef *ADCx) +{ + return (READ_BIT(ADCx->CR1, LL_ADC_IT_AWD1) == (LL_ADC_IT_AWD1)); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup ADC_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +/* Initialization of some features of ADC common parameters and multimode */ +ErrorStatus LL_ADC_CommonDeInit(ADC_Common_TypeDef *ADCxy_COMMON); +ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct); +void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct); + +/* De-initialization of ADC instance, ADC group regular and ADC group injected */ +/* (availability of ADC group injected depends on STM32 families) */ +ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx); + +/* Initialization of some features of ADC instance */ +ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct); +void LL_ADC_StructInit(LL_ADC_InitTypeDef *ADC_InitStruct); + +/* Initialization of some features of ADC instance and ADC group regular */ +ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct); +void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct); + +/* Initialization of some features of ADC instance and ADC group injected */ +ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct); +void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ADC1 || ADC2 || ADC3 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_LL_ADC_H */ + diff --git a/libs/hal/stm32f4xx_ll_bus.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h similarity index 100% rename from libs/hal/stm32f4xx_ll_bus.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_bus.h diff --git a/libs/hal/stm32f4xx_ll_cortex.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h similarity index 100% rename from libs/hal/stm32f4xx_ll_cortex.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_cortex.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h new file mode 100644 index 0000000..0a28006 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_crc.h @@ -0,0 +1,201 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_crc.h + * @author MCD Application Team + * @brief Header file of CRC 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 STM32F4xx_LL_CRC_H +#define STM32F4xx_LL_CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(CRC) + +/** @defgroup CRC_LL CRC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup CRC_LL_Exported_Constants CRC Exported Constants + * @{ + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup CRC_LL_Exported_Macros CRC Exported Macros + * @{ + */ + +/** @defgroup CRC_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in CRC register + * @param __INSTANCE__ CRC Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_CRC_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, __VALUE__) + +/** + * @brief Read a value in CRC register + * @param __INSTANCE__ CRC Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_CRC_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CRC_LL_Exported_Functions CRC Exported Functions + * @{ + */ + +/** @defgroup CRC_LL_EF_Configuration CRC Configuration functions + * @{ + */ + +/** + * @brief Reset the CRC calculation unit. + * @note If Programmable Initial CRC value feature + * is available, also set the Data Register to the value stored in the + * CRC_INIT register, otherwise, reset Data Register to its default value. + * @rmtoll CR RESET LL_CRC_ResetCRCCalculationUnit + * @param CRCx CRC Instance + * @retval None + */ +__STATIC_INLINE void LL_CRC_ResetCRCCalculationUnit(CRC_TypeDef *CRCx) +{ + SET_BIT(CRCx->CR, CRC_CR_RESET); +} + +/** + * @} + */ + +/** @defgroup CRC_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Write given 32-bit data to the CRC calculator + * @rmtoll DR DR LL_CRC_FeedData32 + * @param CRCx CRC Instance + * @param InData value to be provided to CRC calculator between between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_CRC_FeedData32(CRC_TypeDef *CRCx, uint32_t InData) +{ + WRITE_REG(CRCx->DR, InData); +} + +/** + * @brief Return current CRC calculation result. 32 bits value is returned. + * @rmtoll DR DR LL_CRC_ReadData32 + * @param CRCx CRC Instance + * @retval Current CRC calculation result as stored in CRC_DR register (32 bits). + */ +__STATIC_INLINE uint32_t LL_CRC_ReadData32(CRC_TypeDef *CRCx) +{ + return (uint32_t)(READ_REG(CRCx->DR)); +} + +/** + * @brief Return data stored in the Independent Data(IDR) register. + * @note This register can be used as a temporary storage location for one byte. + * @rmtoll IDR IDR LL_CRC_Read_IDR + * @param CRCx CRC Instance + * @retval Value stored in CRC_IDR register (General-purpose 8-bit data register). + */ +__STATIC_INLINE uint32_t LL_CRC_Read_IDR(CRC_TypeDef *CRCx) +{ + return (uint32_t)(READ_REG(CRCx->IDR)); +} + +/** + * @brief Store data in the Independent Data(IDR) register. + * @note This register can be used as a temporary storage location for one byte. + * @rmtoll IDR IDR LL_CRC_Write_IDR + * @param CRCx CRC Instance + * @param InData value to be stored in CRC_IDR register (8-bit) between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_CRC_Write_IDR(CRC_TypeDef *CRCx, uint32_t InData) +{ + *((uint8_t __IO *)(&CRCx->IDR)) = (uint8_t) InData; +} +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup CRC_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(CRC) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_CRC_H */ diff --git a/libs/hal/stm32f4xx_ll_dac.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h similarity index 100% rename from libs/hal/stm32f4xx_ll_dac.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dac.h diff --git a/libs/hal/stm32f4xx_ll_dma.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h similarity index 100% rename from libs/hal/stm32f4xx_ll_dma.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h new file mode 100644 index 0000000..64c57b0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_dma2d.h @@ -0,0 +1,1901 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_dma2d.h + * @author MCD Application Team + * @brief Header file of DMA2D 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 STM32F4xx_LL_DMA2D_H +#define STM32F4xx_LL_DMA2D_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (DMA2D) + +/** @defgroup DMA2D_LL DMA2D + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA2D_LL_Private_Macros DMA2D Private Macros + * @{ + */ + +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA2D_LL_ES_Init_Struct DMA2D Exported Init structures + * @{ + */ + +/** + * @brief LL DMA2D Init Structure Definition + */ +typedef struct +{ + uint32_t Mode; /*!< Specifies the DMA2D transfer mode. + - This parameter can be one value of @ref DMA2D_LL_EC_MODE. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetMode(). */ + + uint32_t ColorMode; /*!< Specifies the color format of the output image. + - This parameter can be one value of @ref DMA2D_LL_EC_OUTPUT_COLOR_MODE. + + This parameter can be modified afterwards using, + unitary function @ref LL_DMA2D_SetOutputColorMode(). */ + + uint32_t OutputBlue; /*!< Specifies the Blue value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputGreen; /*!< Specifies the Green value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x3F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputRed; /*!< Specifies the Red value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputAlpha; /*!< Specifies the Alpha channel of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x01 if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + - This parameter is not considered if RGB888 or RGB565 color mode is selected. + + This parameter can be modified afterwards using, + unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputMemoryAddress; /*!< Specifies the memory address. + - This parameter must be a number between: + Min_Data = 0x0000 and Max_Data = 0xFFFFFFFF. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetOutputMemAddr(). */ + + + + uint32_t LineOffset; /*!< Specifies the output line offset value. + - This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0x3FFF. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetLineOffset(). */ + + uint32_t NbrOfLines; /*!< Specifies the number of lines of the area to be transferred. + - This parameter must be a number between: + Min_Data = 0x0000 and Max_Data = 0xFFFF. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetNbrOfLines(). */ + + uint32_t NbrOfPixelsPerLines; /*!< Specifies the number of pixels per lines of the area to be transferred. + - This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0x3FFF. + + This parameter can be modified afterwards using, + unitary function @ref LL_DMA2D_SetNbrOfPixelsPerLines(). */ + + +} LL_DMA2D_InitTypeDef; + +/** + * @brief LL DMA2D Layer Configuration Structure Definition + */ +typedef struct +{ + uint32_t MemoryAddress; /*!< Specifies the foreground or background memory address. + - This parameter must be a number between: + Min_Data = 0x0000 and Max_Data = 0xFFFFFFFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetMemAddr() for foreground layer, + - @ref LL_DMA2D_BGND_SetMemAddr() for background layer. */ + + uint32_t LineOffset; /*!< Specifies the foreground or background line offset value. + - This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0x3FFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetLineOffset() for foreground layer, + - @ref LL_DMA2D_BGND_SetLineOffset() for background layer. */ + + uint32_t ColorMode; /*!< Specifies the foreground or background color mode. + - This parameter can be one value of @ref DMA2D_LL_EC_INPUT_COLOR_MODE. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetColorMode() for foreground layer, + - @ref LL_DMA2D_BGND_SetColorMode() for background layer. */ + + uint32_t CLUTColorMode; /*!< Specifies the foreground or background CLUT color mode. + - This parameter can be one value of @ref DMA2D_LL_EC_CLUT_COLOR_MODE. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetCLUTColorMode() for foreground layer, + - @ref LL_DMA2D_BGND_SetCLUTColorMode() for background layer. */ + + uint32_t CLUTSize; /*!< Specifies the foreground or background CLUT size. + - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetCLUTSize() for foreground layer, + - @ref LL_DMA2D_BGND_SetCLUTSize() for background layer. */ + + uint32_t AlphaMode; /*!< Specifies the foreground or background alpha mode. + - This parameter can be one value of @ref DMA2D_LL_EC_ALPHA_MODE. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetAlphaMode() for foreground layer, + - @ref LL_DMA2D_BGND_SetAlphaMode() for background layer. */ + + uint32_t Alpha; /*!< Specifies the foreground or background Alpha value. + - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetAlpha() for foreground layer, + - @ref LL_DMA2D_BGND_SetAlpha() for background layer. */ + + uint32_t Blue; /*!< Specifies the foreground or background Blue color value. + - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetBlueColor() for foreground layer, + - @ref LL_DMA2D_BGND_SetBlueColor() for background layer. */ + + uint32_t Green; /*!< Specifies the foreground or background Green color value. + - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetGreenColor() for foreground layer, + - @ref LL_DMA2D_BGND_SetGreenColor() for background layer. */ + + uint32_t Red; /*!< Specifies the foreground or background Red color value. + - This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetRedColor() for foreground layer, + - @ref LL_DMA2D_BGND_SetRedColor() for background layer. */ + + uint32_t CLUTMemoryAddress; /*!< Specifies the foreground or background CLUT memory address. + - This parameter must be a number between: + Min_Data = 0x0000 and Max_Data = 0xFFFFFFFF. + + This parameter can be modified afterwards using unitary functions + - @ref LL_DMA2D_FGND_SetCLUTMemAddr() for foreground layer, + - @ref LL_DMA2D_BGND_SetCLUTMemAddr() for background layer. */ + + + +} LL_DMA2D_LayerCfgTypeDef; + +/** + * @brief LL DMA2D Output Color Structure Definition + */ +typedef struct +{ + uint32_t ColorMode; /*!< Specifies the color format of the output image. + - This parameter can be one value of @ref DMA2D_LL_EC_OUTPUT_COLOR_MODE. + + This parameter can be modified afterwards using + unitary function @ref LL_DMA2D_SetOutputColorMode(). */ + + uint32_t OutputBlue; /*!< Specifies the Blue value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards using, + unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputGreen; /*!< Specifies the Green value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x3F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputRed; /*!< Specifies the Red value of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if RGB888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if RGB565 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x1F if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + + uint32_t OutputAlpha; /*!< Specifies the Alpha channel of the output image. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0xFF if ARGB8888 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x01 if ARGB1555 color mode is selected. + - This parameter must be a number between: + Min_Data = 0x00 and Max_Data = 0x0F if ARGB4444 color mode is selected. + - This parameter is not considered if RGB888 or RGB565 color mode is selected. + + This parameter can be modified afterwards, + using unitary function @ref LL_DMA2D_SetOutputColor() or configuration + function @ref LL_DMA2D_ConfigOutputColor(). */ + +} LL_DMA2D_ColorTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup DMA2D_LL_Exported_Constants DMA2D Exported Constants + * @{ + */ + +/** @defgroup DMA2D_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_DMA2D_ReadReg function + * @{ + */ +#define LL_DMA2D_FLAG_CEIF DMA2D_ISR_CEIF /*!< Configuration Error Interrupt Flag */ +#define LL_DMA2D_FLAG_CTCIF DMA2D_ISR_CTCIF /*!< CLUT Transfer Complete Interrupt Flag */ +#define LL_DMA2D_FLAG_CAEIF DMA2D_ISR_CAEIF /*!< CLUT Access Error Interrupt Flag */ +#define LL_DMA2D_FLAG_TWIF DMA2D_ISR_TWIF /*!< Transfer Watermark Interrupt Flag */ +#define LL_DMA2D_FLAG_TCIF DMA2D_ISR_TCIF /*!< Transfer Complete Interrupt Flag */ +#define LL_DMA2D_FLAG_TEIF DMA2D_ISR_TEIF /*!< Transfer Error Interrupt Flag */ +/** + * @} + */ + +/** @defgroup DMA2D_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_DMA2D_ReadReg and LL_DMA2D_WriteReg functions + * @{ + */ +#define LL_DMA2D_IT_CEIE DMA2D_CR_CEIE /*!< Configuration Error Interrupt */ +#define LL_DMA2D_IT_CTCIE DMA2D_CR_CTCIE /*!< CLUT Transfer Complete Interrupt */ +#define LL_DMA2D_IT_CAEIE DMA2D_CR_CAEIE /*!< CLUT Access Error Interrupt */ +#define LL_DMA2D_IT_TWIE DMA2D_CR_TWIE /*!< Transfer Watermark Interrupt */ +#define LL_DMA2D_IT_TCIE DMA2D_CR_TCIE /*!< Transfer Complete Interrupt */ +#define LL_DMA2D_IT_TEIE DMA2D_CR_TEIE /*!< Transfer Error Interrupt */ +/** + * @} + */ + +/** @defgroup DMA2D_LL_EC_MODE Mode + * @{ + */ +#define LL_DMA2D_MODE_M2M 0x00000000U /*!< DMA2D memory to memory transfer mode */ +#define LL_DMA2D_MODE_M2M_PFC DMA2D_CR_MODE_0 /*!< DMA2D memory to memory with pixel format conversion transfer mode */ +#define LL_DMA2D_MODE_M2M_BLEND DMA2D_CR_MODE_1 /*!< DMA2D memory to memory with blending transfer mode */ +#define LL_DMA2D_MODE_R2M DMA2D_CR_MODE /*!< DMA2D register to memory transfer mode */ +/** + * @} + */ + +/** @defgroup DMA2D_LL_EC_OUTPUT_COLOR_MODE Output Color Mode + * @{ + */ +#define LL_DMA2D_OUTPUT_MODE_ARGB8888 0x00000000U /*!< ARGB8888 */ +#define LL_DMA2D_OUTPUT_MODE_RGB888 DMA2D_OPFCCR_CM_0 /*!< RGB888 */ +#define LL_DMA2D_OUTPUT_MODE_RGB565 DMA2D_OPFCCR_CM_1 /*!< RGB565 */ +#define LL_DMA2D_OUTPUT_MODE_ARGB1555 (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /*!< ARGB1555 */ +#define LL_DMA2D_OUTPUT_MODE_ARGB4444 DMA2D_OPFCCR_CM_2 /*!< ARGB4444 */ +/** + * @} + */ + +/** @defgroup DMA2D_LL_EC_INPUT_COLOR_MODE Input Color Mode + * @{ + */ +#define LL_DMA2D_INPUT_MODE_ARGB8888 0x00000000U /*!< ARGB8888 */ +#define LL_DMA2D_INPUT_MODE_RGB888 DMA2D_FGPFCCR_CM_0 /*!< RGB888 */ +#define LL_DMA2D_INPUT_MODE_RGB565 DMA2D_FGPFCCR_CM_1 /*!< RGB565 */ +#define LL_DMA2D_INPUT_MODE_ARGB1555 (DMA2D_FGPFCCR_CM_0|DMA2D_FGPFCCR_CM_1) /*!< ARGB1555 */ +#define LL_DMA2D_INPUT_MODE_ARGB4444 DMA2D_FGPFCCR_CM_2 /*!< ARGB4444 */ +#define LL_DMA2D_INPUT_MODE_L8 (DMA2D_FGPFCCR_CM_0|DMA2D_FGPFCCR_CM_2) /*!< L8 */ +#define LL_DMA2D_INPUT_MODE_AL44 (DMA2D_FGPFCCR_CM_1|DMA2D_FGPFCCR_CM_2) /*!< AL44 */ +#define LL_DMA2D_INPUT_MODE_AL88 (DMA2D_FGPFCCR_CM_0|DMA2D_FGPFCCR_CM_1|DMA2D_FGPFCCR_CM_2) /*!< AL88 */ +#define LL_DMA2D_INPUT_MODE_L4 DMA2D_FGPFCCR_CM_3 /*!< L4 */ +#define LL_DMA2D_INPUT_MODE_A8 (DMA2D_FGPFCCR_CM_0|DMA2D_FGPFCCR_CM_3) /*!< A8 */ +#define LL_DMA2D_INPUT_MODE_A4 (DMA2D_FGPFCCR_CM_1|DMA2D_FGPFCCR_CM_3) /*!< A4 */ +/** + * @} + */ + +/** @defgroup DMA2D_LL_EC_ALPHA_MODE Alpha Mode + * @{ + */ +#define LL_DMA2D_ALPHA_MODE_NO_MODIF 0x00000000U /*!< No modification of the alpha channel value */ +#define LL_DMA2D_ALPHA_MODE_REPLACE DMA2D_FGPFCCR_AM_0 /*!< Replace original alpha channel value by + programmed alpha value */ +#define LL_DMA2D_ALPHA_MODE_COMBINE DMA2D_FGPFCCR_AM_1 /*!< Replace original alpha channel value by + programmed alpha value with, + original alpha channel value */ +/** + * @} + */ + + + + +/** @defgroup DMA2D_LL_EC_CLUT_COLOR_MODE CLUT Color Mode + * @{ + */ +#define LL_DMA2D_CLUT_COLOR_MODE_ARGB8888 0x00000000U /*!< ARGB8888 */ +#define LL_DMA2D_CLUT_COLOR_MODE_RGB888 DMA2D_FGPFCCR_CCM /*!< RGB888 */ +/** + * @} + */ + + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup DMA2D_LL_Exported_Macros DMA2D Exported Macros + * @{ + */ + +/** @defgroup DMA2D_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in DMA2D register. + * @param __INSTANCE__ DMA2D Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_DMA2D_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG((__INSTANCE__)->__REG__, (__VALUE__)) + +/** + * @brief Read a value in DMA2D register. + * @param __INSTANCE__ DMA2D Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_DMA2D_ReadReg(__INSTANCE__, __REG__) READ_REG((__INSTANCE__)->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DMA2D_LL_Exported_Functions DMA2D Exported Functions + * @{ + */ + +/** @defgroup DMA2D_LL_EF_Configuration Configuration Functions + * @{ + */ + +/** + * @brief Start a DMA2D transfer. + * @rmtoll CR START LL_DMA2D_Start + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_Start(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_START); +} + +/** + * @brief Indicate if a DMA2D transfer is ongoing. + * @rmtoll CR START LL_DMA2D_IsTransferOngoing + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsTransferOngoing(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_START) == (DMA2D_CR_START)) ? 1UL : 0UL); +} + +/** + * @brief Suspend DMA2D transfer. + * @note This API can be used to suspend automatic foreground or background CLUT loading. + * @rmtoll CR SUSP LL_DMA2D_Suspend + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_Suspend(DMA2D_TypeDef *DMA2Dx) +{ + MODIFY_REG(DMA2Dx->CR, DMA2D_CR_SUSP | DMA2D_CR_START, DMA2D_CR_SUSP); +} + +/** + * @brief Resume DMA2D transfer. + * @note This API can be used to resume automatic foreground or background CLUT loading. + * @rmtoll CR SUSP LL_DMA2D_Resume + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_Resume(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_SUSP | DMA2D_CR_START); +} + +/** + * @brief Indicate if DMA2D transfer is suspended. + * @note This API can be used to indicate whether or not automatic foreground or + * background CLUT loading is suspended. + * @rmtoll CR SUSP LL_DMA2D_IsSuspended + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsSuspended(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_SUSP) == (DMA2D_CR_SUSP)) ? 1UL : 0UL); +} + +/** + * @brief Abort DMA2D transfer. + * @note This API can be used to abort automatic foreground or background CLUT loading. + * @rmtoll CR ABORT LL_DMA2D_Abort + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_Abort(DMA2D_TypeDef *DMA2Dx) +{ + MODIFY_REG(DMA2Dx->CR, DMA2D_CR_ABORT | DMA2D_CR_START, DMA2D_CR_ABORT); +} + +/** + * @brief Indicate if DMA2D transfer is aborted. + * @note This API can be used to indicate whether or not automatic foreground or + * background CLUT loading is aborted. + * @rmtoll CR ABORT LL_DMA2D_IsAborted + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsAborted(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_ABORT) == (DMA2D_CR_ABORT)) ? 1UL : 0UL); +} + +/** + * @brief Set DMA2D mode. + * @rmtoll CR MODE LL_DMA2D_SetMode + * @param DMA2Dx DMA2D Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_MODE_M2M + * @arg @ref LL_DMA2D_MODE_M2M_PFC + * @arg @ref LL_DMA2D_MODE_M2M_BLEND + * @arg @ref LL_DMA2D_MODE_R2M + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetMode(DMA2D_TypeDef *DMA2Dx, uint32_t Mode) +{ + MODIFY_REG(DMA2Dx->CR, DMA2D_CR_MODE, Mode); +} + +/** + * @brief Return DMA2D mode + * @rmtoll CR MODE LL_DMA2D_GetMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_MODE_M2M + * @arg @ref LL_DMA2D_MODE_M2M_PFC + * @arg @ref LL_DMA2D_MODE_M2M_BLEND + * @arg @ref LL_DMA2D_MODE_R2M + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->CR, DMA2D_CR_MODE)); +} + +/** + * @brief Set DMA2D output color mode. + * @rmtoll OPFCCR CM LL_DMA2D_SetOutputColorMode + * @param DMA2Dx DMA2D Instance + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetOutputColorMode(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + MODIFY_REG(DMA2Dx->OPFCCR, DMA2D_OPFCCR_CM, ColorMode); +} + +/** + * @brief Return DMA2D output color mode. + * @rmtoll OPFCCR CM LL_DMA2D_GetOutputColorMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetOutputColorMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->OPFCCR, DMA2D_OPFCCR_CM)); +} + + + + +/** + * @brief Set DMA2D line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll OOR LO LL_DMA2D_SetLineOffset + * @param DMA2Dx DMA2D Instance + * @param LineOffset Value between Min_Data=0 and Max_Data=0x3FFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetLineOffset(DMA2D_TypeDef *DMA2Dx, uint32_t LineOffset) +{ + MODIFY_REG(DMA2Dx->OOR, DMA2D_OOR_LO, LineOffset); +} + +/** + * @brief Return DMA2D line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll OOR LO LL_DMA2D_GetLineOffset + * @param DMA2Dx DMA2D Instance + * @retval Line offset value between Min_Data=0 and Max_Data=0x3FFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetLineOffset(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->OOR, DMA2D_OOR_LO)); +} + +/** + * @brief Set DMA2D number of pixels per lines, expressed on 14 bits ([13:0] bits). + * @rmtoll NLR PL LL_DMA2D_SetNbrOfPixelsPerLines + * @param DMA2Dx DMA2D Instance + * @param NbrOfPixelsPerLines Value between Min_Data=0 and Max_Data=0x3FFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetNbrOfPixelsPerLines(DMA2D_TypeDef *DMA2Dx, uint32_t NbrOfPixelsPerLines) +{ + MODIFY_REG(DMA2Dx->NLR, DMA2D_NLR_PL, (NbrOfPixelsPerLines << DMA2D_NLR_PL_Pos)); +} + +/** + * @brief Return DMA2D number of pixels per lines, expressed on 14 bits ([13:0] bits) + * @rmtoll NLR PL LL_DMA2D_GetNbrOfPixelsPerLines + * @param DMA2Dx DMA2D Instance + * @retval Number of pixels per lines value between Min_Data=0 and Max_Data=0x3FFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetNbrOfPixelsPerLines(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->NLR, DMA2D_NLR_PL) >> DMA2D_NLR_PL_Pos); +} + +/** + * @brief Set DMA2D number of lines, expressed on 16 bits ([15:0] bits). + * @rmtoll NLR NL LL_DMA2D_SetNbrOfLines + * @param DMA2Dx DMA2D Instance + * @param NbrOfLines Value between Min_Data=0 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetNbrOfLines(DMA2D_TypeDef *DMA2Dx, uint32_t NbrOfLines) +{ + MODIFY_REG(DMA2Dx->NLR, DMA2D_NLR_NL, NbrOfLines); +} + +/** + * @brief Return DMA2D number of lines, expressed on 16 bits ([15:0] bits). + * @rmtoll NLR NL LL_DMA2D_GetNbrOfLines + * @param DMA2Dx DMA2D Instance + * @retval Number of lines value between Min_Data=0 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetNbrOfLines(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->NLR, DMA2D_NLR_NL)); +} + +/** + * @brief Set DMA2D output memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll OMAR MA LL_DMA2D_SetOutputMemAddr + * @param DMA2Dx DMA2D Instance + * @param OutputMemoryAddress Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetOutputMemAddr(DMA2D_TypeDef *DMA2Dx, uint32_t OutputMemoryAddress) +{ + LL_DMA2D_WriteReg(DMA2Dx, OMAR, OutputMemoryAddress); +} + +/** + * @brief Get DMA2D output memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll OMAR MA LL_DMA2D_GetOutputMemAddr + * @param DMA2Dx DMA2D Instance + * @retval Output memory address value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetOutputMemAddr(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(LL_DMA2D_ReadReg(DMA2Dx, OMAR)); +} + +/** + * @brief Set DMA2D output color, expressed on 32 bits ([31:0] bits). + * @note Output color format depends on output color mode, ARGB8888, RGB888, + * RGB565, ARGB1555 or ARGB4444. + * @note LL_DMA2D_ConfigOutputColor() API may be used instead if colors values formatting + * with respect to color mode is not done by the user code. + * @rmtoll OCOLR BLUE LL_DMA2D_SetOutputColor\n + * OCOLR GREEN LL_DMA2D_SetOutputColor\n + * OCOLR RED LL_DMA2D_SetOutputColor\n + * OCOLR ALPHA LL_DMA2D_SetOutputColor + * @param DMA2Dx DMA2D Instance + * @param OutputColor Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetOutputColor(DMA2D_TypeDef *DMA2Dx, uint32_t OutputColor) +{ + MODIFY_REG(DMA2Dx->OCOLR, (DMA2D_OCOLR_BLUE_1 | DMA2D_OCOLR_GREEN_1 | DMA2D_OCOLR_RED_1 | DMA2D_OCOLR_ALPHA_1), \ + OutputColor); +} + +/** + * @brief Get DMA2D output color, expressed on 32 bits ([31:0] bits). + * @note Alpha channel and red, green, blue color values must be retrieved from the returned + * value based on the output color mode (ARGB8888, RGB888, RGB565, ARGB1555 or ARGB4444) + * as set by @ref LL_DMA2D_SetOutputColorMode. + * @rmtoll OCOLR BLUE LL_DMA2D_GetOutputColor\n + * OCOLR GREEN LL_DMA2D_GetOutputColor\n + * OCOLR RED LL_DMA2D_GetOutputColor\n + * OCOLR ALPHA LL_DMA2D_GetOutputColor + * @param DMA2Dx DMA2D Instance + * @retval Output color value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetOutputColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->OCOLR, \ + (DMA2D_OCOLR_BLUE_1 | DMA2D_OCOLR_GREEN_1 | DMA2D_OCOLR_RED_1 | DMA2D_OCOLR_ALPHA_1))); +} + +/** + * @brief Set DMA2D line watermark, expressed on 16 bits ([15:0] bits). + * @rmtoll LWR LW LL_DMA2D_SetLineWatermark + * @param DMA2Dx DMA2D Instance + * @param LineWatermark Value between Min_Data=0 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetLineWatermark(DMA2D_TypeDef *DMA2Dx, uint32_t LineWatermark) +{ + MODIFY_REG(DMA2Dx->LWR, DMA2D_LWR_LW, LineWatermark); +} + +/** + * @brief Return DMA2D line watermark, expressed on 16 bits ([15:0] bits). + * @rmtoll LWR LW LL_DMA2D_GetLineWatermark + * @param DMA2Dx DMA2D Instance + * @retval Line watermark value between Min_Data=0 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetLineWatermark(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->LWR, DMA2D_LWR_LW)); +} + +/** + * @brief Set DMA2D dead time, expressed on 8 bits ([7:0] bits). + * @rmtoll AMTCR DT LL_DMA2D_SetDeadTime + * @param DMA2Dx DMA2D Instance + * @param DeadTime Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_SetDeadTime(DMA2D_TypeDef *DMA2Dx, uint32_t DeadTime) +{ + MODIFY_REG(DMA2Dx->AMTCR, DMA2D_AMTCR_DT, (DeadTime << DMA2D_AMTCR_DT_Pos)); +} + +/** + * @brief Return DMA2D dead time, expressed on 8 bits ([7:0] bits). + * @rmtoll AMTCR DT LL_DMA2D_GetDeadTime + * @param DMA2Dx DMA2D Instance + * @retval Dead time value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_GetDeadTime(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->AMTCR, DMA2D_AMTCR_DT) >> DMA2D_AMTCR_DT_Pos); +} + +/** + * @brief Enable DMA2D dead time functionality. + * @rmtoll AMTCR EN LL_DMA2D_EnableDeadTime + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableDeadTime(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->AMTCR, DMA2D_AMTCR_EN); +} + +/** + * @brief Disable DMA2D dead time functionality. + * @rmtoll AMTCR EN LL_DMA2D_DisableDeadTime + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableDeadTime(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->AMTCR, DMA2D_AMTCR_EN); +} + +/** + * @brief Indicate if DMA2D dead time functionality is enabled. + * @rmtoll AMTCR EN LL_DMA2D_IsEnabledDeadTime + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledDeadTime(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->AMTCR, DMA2D_AMTCR_EN) == (DMA2D_AMTCR_EN)) ? 1UL : 0UL); +} + +/** @defgroup DMA2D_LL_EF_FGND_Configuration Foreground Configuration Functions + * @{ + */ + +/** + * @brief Set DMA2D foreground memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll FGMAR MA LL_DMA2D_FGND_SetMemAddr + * @param DMA2Dx DMA2D Instance + * @param MemoryAddress Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetMemAddr(DMA2D_TypeDef *DMA2Dx, uint32_t MemoryAddress) +{ + LL_DMA2D_WriteReg(DMA2Dx, FGMAR, MemoryAddress); +} + +/** + * @brief Get DMA2D foreground memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll FGMAR MA LL_DMA2D_FGND_GetMemAddr + * @param DMA2Dx DMA2D Instance + * @retval Foreground memory address value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetMemAddr(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(LL_DMA2D_ReadReg(DMA2Dx, FGMAR)); +} + +/** + * @brief Enable DMA2D foreground CLUT loading. + * @rmtoll FGPFCCR START LL_DMA2D_FGND_EnableCLUTLoad + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_EnableCLUTLoad(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_START); +} + +/** + * @brief Indicate if DMA2D foreground CLUT loading is enabled. + * @rmtoll FGPFCCR START LL_DMA2D_FGND_IsEnabledCLUTLoad + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_IsEnabledCLUTLoad(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_START) == (DMA2D_FGPFCCR_START)) ? 1UL : 0UL); +} + +/** + * @brief Set DMA2D foreground color mode. + * @rmtoll FGPFCCR CM LL_DMA2D_FGND_SetColorMode + * @param DMA2Dx DMA2D Instance + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB4444 + * @arg @ref LL_DMA2D_INPUT_MODE_L8 + * @arg @ref LL_DMA2D_INPUT_MODE_AL44 + * @arg @ref LL_DMA2D_INPUT_MODE_AL88 + * @arg @ref LL_DMA2D_INPUT_MODE_L4 + * @arg @ref LL_DMA2D_INPUT_MODE_A8 + * @arg @ref LL_DMA2D_INPUT_MODE_A4 + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetColorMode(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + MODIFY_REG(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CM, ColorMode); +} + +/** + * @brief Return DMA2D foreground color mode. + * @rmtoll FGPFCCR CM LL_DMA2D_FGND_GetColorMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB4444 + * @arg @ref LL_DMA2D_INPUT_MODE_L8 + * @arg @ref LL_DMA2D_INPUT_MODE_AL44 + * @arg @ref LL_DMA2D_INPUT_MODE_AL88 + * @arg @ref LL_DMA2D_INPUT_MODE_L4 + * @arg @ref LL_DMA2D_INPUT_MODE_A8 + * @arg @ref LL_DMA2D_INPUT_MODE_A4 + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetColorMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CM)); +} + +/** + * @brief Set DMA2D foreground alpha mode. + * @rmtoll FGPFCCR AM LL_DMA2D_FGND_SetAlphaMode + * @param DMA2Dx DMA2D Instance + * @param AphaMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_ALPHA_MODE_NO_MODIF + * @arg @ref LL_DMA2D_ALPHA_MODE_REPLACE + * @arg @ref LL_DMA2D_ALPHA_MODE_COMBINE + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetAlphaMode(DMA2D_TypeDef *DMA2Dx, uint32_t AphaMode) +{ + MODIFY_REG(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_AM, AphaMode); +} + +/** + * @brief Return DMA2D foreground alpha mode. + * @rmtoll FGPFCCR AM LL_DMA2D_FGND_GetAlphaMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_ALPHA_MODE_NO_MODIF + * @arg @ref LL_DMA2D_ALPHA_MODE_REPLACE + * @arg @ref LL_DMA2D_ALPHA_MODE_COMBINE + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetAlphaMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_AM)); +} + +/** + * @brief Set DMA2D foreground alpha value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGPFCCR ALPHA LL_DMA2D_FGND_SetAlpha + * @param DMA2Dx DMA2D Instance + * @param Alpha Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetAlpha(DMA2D_TypeDef *DMA2Dx, uint32_t Alpha) +{ + MODIFY_REG(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_ALPHA, (Alpha << DMA2D_FGPFCCR_ALPHA_Pos)); +} + +/** + * @brief Return DMA2D foreground alpha value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGPFCCR ALPHA LL_DMA2D_FGND_GetAlpha + * @param DMA2Dx DMA2D Instance + * @retval Alpha value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetAlpha(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_ALPHA) >> DMA2D_FGPFCCR_ALPHA_Pos); +} + + +/** + * @brief Set DMA2D foreground line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll FGOR LO LL_DMA2D_FGND_SetLineOffset + * @param DMA2Dx DMA2D Instance + * @param LineOffset Value between Min_Data=0 and Max_Data=0x3FF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetLineOffset(DMA2D_TypeDef *DMA2Dx, uint32_t LineOffset) +{ + MODIFY_REG(DMA2Dx->FGOR, DMA2D_FGOR_LO, LineOffset); +} + +/** + * @brief Return DMA2D foreground line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll FGOR LO LL_DMA2D_FGND_GetLineOffset + * @param DMA2Dx DMA2D Instance + * @retval Foreground line offset value between Min_Data=0 and Max_Data=0x3FF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetLineOffset(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGOR, DMA2D_FGOR_LO)); +} + +/** + * @brief Set DMA2D foreground color values, expressed on 24 bits ([23:0] bits). + * @rmtoll FGCOLR RED LL_DMA2D_FGND_SetColor + * @rmtoll FGCOLR GREEN LL_DMA2D_FGND_SetColor + * @rmtoll FGCOLR BLUE LL_DMA2D_FGND_SetColor + * @param DMA2Dx DMA2D Instance + * @param Red Value between Min_Data=0 and Max_Data=0xFF + * @param Green Value between Min_Data=0 and Max_Data=0xFF + * @param Blue Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetColor(DMA2D_TypeDef *DMA2Dx, uint32_t Red, uint32_t Green, uint32_t Blue) +{ + MODIFY_REG(DMA2Dx->FGCOLR, (DMA2D_FGCOLR_RED | DMA2D_FGCOLR_GREEN | DMA2D_FGCOLR_BLUE), \ + ((Red << DMA2D_FGCOLR_RED_Pos) | (Green << DMA2D_FGCOLR_GREEN_Pos) | Blue)); +} + +/** + * @brief Set DMA2D foreground red color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR RED LL_DMA2D_FGND_SetRedColor + * @param DMA2Dx DMA2D Instance + * @param Red Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetRedColor(DMA2D_TypeDef *DMA2Dx, uint32_t Red) +{ + MODIFY_REG(DMA2Dx->FGCOLR, DMA2D_FGCOLR_RED, (Red << DMA2D_FGCOLR_RED_Pos)); +} + +/** + * @brief Return DMA2D foreground red color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR RED LL_DMA2D_FGND_GetRedColor + * @param DMA2Dx DMA2D Instance + * @retval Red color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetRedColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGCOLR, DMA2D_FGCOLR_RED) >> DMA2D_FGCOLR_RED_Pos); +} + +/** + * @brief Set DMA2D foreground green color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR GREEN LL_DMA2D_FGND_SetGreenColor + * @param DMA2Dx DMA2D Instance + * @param Green Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetGreenColor(DMA2D_TypeDef *DMA2Dx, uint32_t Green) +{ + MODIFY_REG(DMA2Dx->FGCOLR, DMA2D_FGCOLR_GREEN, (Green << DMA2D_FGCOLR_GREEN_Pos)); +} + +/** + * @brief Return DMA2D foreground green color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR GREEN LL_DMA2D_FGND_GetGreenColor + * @param DMA2Dx DMA2D Instance + * @retval Green color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetGreenColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGCOLR, DMA2D_FGCOLR_GREEN) >> DMA2D_FGCOLR_GREEN_Pos); +} + +/** + * @brief Set DMA2D foreground blue color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR BLUE LL_DMA2D_FGND_SetBlueColor + * @param DMA2Dx DMA2D Instance + * @param Blue Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetBlueColor(DMA2D_TypeDef *DMA2Dx, uint32_t Blue) +{ + MODIFY_REG(DMA2Dx->FGCOLR, DMA2D_FGCOLR_BLUE, Blue); +} + +/** + * @brief Return DMA2D foreground blue color value, expressed on 8 bits ([7:0] bits). + * @rmtoll FGCOLR BLUE LL_DMA2D_FGND_GetBlueColor + * @param DMA2Dx DMA2D Instance + * @retval Blue color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetBlueColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGCOLR, DMA2D_FGCOLR_BLUE)); +} + +/** + * @brief Set DMA2D foreground CLUT memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll FGCMAR MA LL_DMA2D_FGND_SetCLUTMemAddr + * @param DMA2Dx DMA2D Instance + * @param CLUTMemoryAddress Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetCLUTMemAddr(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTMemoryAddress) +{ + LL_DMA2D_WriteReg(DMA2Dx, FGCMAR, CLUTMemoryAddress); +} + +/** + * @brief Get DMA2D foreground CLUT memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll FGCMAR MA LL_DMA2D_FGND_GetCLUTMemAddr + * @param DMA2Dx DMA2D Instance + * @retval Foreground CLUT memory address value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetCLUTMemAddr(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(LL_DMA2D_ReadReg(DMA2Dx, FGCMAR)); +} + +/** + * @brief Set DMA2D foreground CLUT size, expressed on 8 bits ([7:0] bits). + * @rmtoll FGPFCCR CS LL_DMA2D_FGND_SetCLUTSize + * @param DMA2Dx DMA2D Instance + * @param CLUTSize Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetCLUTSize(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTSize) +{ + MODIFY_REG(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CS, (CLUTSize << DMA2D_FGPFCCR_CS_Pos)); +} + +/** + * @brief Get DMA2D foreground CLUT size, expressed on 8 bits ([7:0] bits). + * @rmtoll FGPFCCR CS LL_DMA2D_FGND_GetCLUTSize + * @param DMA2Dx DMA2D Instance + * @retval Foreground CLUT size value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetCLUTSize(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CS) >> DMA2D_FGPFCCR_CS_Pos); +} + +/** + * @brief Set DMA2D foreground CLUT color mode. + * @rmtoll FGPFCCR CCM LL_DMA2D_FGND_SetCLUTColorMode + * @param DMA2Dx DMA2D Instance + * @param CLUTColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_ARGB8888 + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_RGB888 + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_FGND_SetCLUTColorMode(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTColorMode) +{ + MODIFY_REG(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CCM, CLUTColorMode); +} + +/** + * @brief Return DMA2D foreground CLUT color mode. + * @rmtoll FGPFCCR CCM LL_DMA2D_FGND_GetCLUTColorMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_ARGB8888 + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_RGB888 + */ +__STATIC_INLINE uint32_t LL_DMA2D_FGND_GetCLUTColorMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->FGPFCCR, DMA2D_FGPFCCR_CCM)); +} + +/** + * @} + */ + +/** @defgroup DMA2D_LL_EF_BGND_Configuration Background Configuration Functions + * @{ + */ + +/** + * @brief Set DMA2D background memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll BGMAR MA LL_DMA2D_BGND_SetMemAddr + * @param DMA2Dx DMA2D Instance + * @param MemoryAddress Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetMemAddr(DMA2D_TypeDef *DMA2Dx, uint32_t MemoryAddress) +{ + LL_DMA2D_WriteReg(DMA2Dx, BGMAR, MemoryAddress); +} + +/** + * @brief Get DMA2D background memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll BGMAR MA LL_DMA2D_BGND_GetMemAddr + * @param DMA2Dx DMA2D Instance + * @retval Background memory address value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetMemAddr(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(LL_DMA2D_ReadReg(DMA2Dx, BGMAR)); +} + +/** + * @brief Enable DMA2D background CLUT loading. + * @rmtoll BGPFCCR START LL_DMA2D_BGND_EnableCLUTLoad + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_EnableCLUTLoad(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_START); +} + +/** + * @brief Indicate if DMA2D background CLUT loading is enabled. + * @rmtoll BGPFCCR START LL_DMA2D_BGND_IsEnabledCLUTLoad + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_IsEnabledCLUTLoad(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_START) == (DMA2D_BGPFCCR_START)) ? 1UL : 0UL); +} + +/** + * @brief Set DMA2D background color mode. + * @rmtoll BGPFCCR CM LL_DMA2D_BGND_SetColorMode + * @param DMA2Dx DMA2D Instance + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB4444 + * @arg @ref LL_DMA2D_INPUT_MODE_L8 + * @arg @ref LL_DMA2D_INPUT_MODE_AL44 + * @arg @ref LL_DMA2D_INPUT_MODE_AL88 + * @arg @ref LL_DMA2D_INPUT_MODE_L4 + * @arg @ref LL_DMA2D_INPUT_MODE_A8 + * @arg @ref LL_DMA2D_INPUT_MODE_A4 + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetColorMode(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + MODIFY_REG(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CM, ColorMode); +} + +/** + * @brief Return DMA2D background color mode. + * @rmtoll BGPFCCR CM LL_DMA2D_BGND_GetColorMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_INPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_INPUT_MODE_ARGB4444 + * @arg @ref LL_DMA2D_INPUT_MODE_L8 + * @arg @ref LL_DMA2D_INPUT_MODE_AL44 + * @arg @ref LL_DMA2D_INPUT_MODE_AL88 + * @arg @ref LL_DMA2D_INPUT_MODE_L4 + * @arg @ref LL_DMA2D_INPUT_MODE_A8 + * @arg @ref LL_DMA2D_INPUT_MODE_A4 + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetColorMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CM)); +} + +/** + * @brief Set DMA2D background alpha mode. + * @rmtoll BGPFCCR AM LL_DMA2D_BGND_SetAlphaMode + * @param DMA2Dx DMA2D Instance + * @param AphaMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_ALPHA_MODE_NO_MODIF + * @arg @ref LL_DMA2D_ALPHA_MODE_REPLACE + * @arg @ref LL_DMA2D_ALPHA_MODE_COMBINE + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetAlphaMode(DMA2D_TypeDef *DMA2Dx, uint32_t AphaMode) +{ + MODIFY_REG(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_AM, AphaMode); +} + +/** + * @brief Return DMA2D background alpha mode. + * @rmtoll BGPFCCR AM LL_DMA2D_BGND_GetAlphaMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_ALPHA_MODE_NO_MODIF + * @arg @ref LL_DMA2D_ALPHA_MODE_REPLACE + * @arg @ref LL_DMA2D_ALPHA_MODE_COMBINE + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetAlphaMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_AM)); +} + +/** + * @brief Set DMA2D background alpha value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGPFCCR ALPHA LL_DMA2D_BGND_SetAlpha + * @param DMA2Dx DMA2D Instance + * @param Alpha Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetAlpha(DMA2D_TypeDef *DMA2Dx, uint32_t Alpha) +{ + MODIFY_REG(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_ALPHA, (Alpha << DMA2D_BGPFCCR_ALPHA_Pos)); +} + +/** + * @brief Return DMA2D background alpha value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGPFCCR ALPHA LL_DMA2D_BGND_GetAlpha + * @param DMA2Dx DMA2D Instance + * @retval Alpha value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetAlpha(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_ALPHA) >> DMA2D_BGPFCCR_ALPHA_Pos); +} + + +/** + * @brief Set DMA2D background line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll BGOR LO LL_DMA2D_BGND_SetLineOffset + * @param DMA2Dx DMA2D Instance + * @param LineOffset Value between Min_Data=0 and Max_Data=0x3FF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetLineOffset(DMA2D_TypeDef *DMA2Dx, uint32_t LineOffset) +{ + MODIFY_REG(DMA2Dx->BGOR, DMA2D_BGOR_LO, LineOffset); +} + +/** + * @brief Return DMA2D background line offset, expressed on 14 bits ([13:0] bits). + * @rmtoll BGOR LO LL_DMA2D_BGND_GetLineOffset + * @param DMA2Dx DMA2D Instance + * @retval Background line offset value between Min_Data=0 and Max_Data=0x3FF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetLineOffset(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGOR, DMA2D_BGOR_LO)); +} + +/** + * @brief Set DMA2D background color values, expressed on 24 bits ([23:0] bits). + * @rmtoll BGCOLR RED LL_DMA2D_BGND_SetColor + * @rmtoll BGCOLR GREEN LL_DMA2D_BGND_SetColor + * @rmtoll BGCOLR BLUE LL_DMA2D_BGND_SetColor + * @param DMA2Dx DMA2D Instance + * @param Red Value between Min_Data=0 and Max_Data=0xFF + * @param Green Value between Min_Data=0 and Max_Data=0xFF + * @param Blue Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetColor(DMA2D_TypeDef *DMA2Dx, uint32_t Red, uint32_t Green, uint32_t Blue) +{ + MODIFY_REG(DMA2Dx->BGCOLR, (DMA2D_BGCOLR_RED | DMA2D_BGCOLR_GREEN | DMA2D_BGCOLR_BLUE), \ + ((Red << DMA2D_BGCOLR_RED_Pos) | (Green << DMA2D_BGCOLR_GREEN_Pos) | Blue)); +} + +/** + * @brief Set DMA2D background red color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR RED LL_DMA2D_BGND_SetRedColor + * @param DMA2Dx DMA2D Instance + * @param Red Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetRedColor(DMA2D_TypeDef *DMA2Dx, uint32_t Red) +{ + MODIFY_REG(DMA2Dx->BGCOLR, DMA2D_BGCOLR_RED, (Red << DMA2D_BGCOLR_RED_Pos)); +} + +/** + * @brief Return DMA2D background red color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR RED LL_DMA2D_BGND_GetRedColor + * @param DMA2Dx DMA2D Instance + * @retval Red color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetRedColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGCOLR, DMA2D_BGCOLR_RED) >> DMA2D_BGCOLR_RED_Pos); +} + +/** + * @brief Set DMA2D background green color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR GREEN LL_DMA2D_BGND_SetGreenColor + * @param DMA2Dx DMA2D Instance + * @param Green Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetGreenColor(DMA2D_TypeDef *DMA2Dx, uint32_t Green) +{ + MODIFY_REG(DMA2Dx->BGCOLR, DMA2D_BGCOLR_GREEN, (Green << DMA2D_BGCOLR_GREEN_Pos)); +} + +/** + * @brief Return DMA2D background green color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR GREEN LL_DMA2D_BGND_GetGreenColor + * @param DMA2Dx DMA2D Instance + * @retval Green color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetGreenColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGCOLR, DMA2D_BGCOLR_GREEN) >> DMA2D_BGCOLR_GREEN_Pos); +} + +/** + * @brief Set DMA2D background blue color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR BLUE LL_DMA2D_BGND_SetBlueColor + * @param DMA2Dx DMA2D Instance + * @param Blue Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetBlueColor(DMA2D_TypeDef *DMA2Dx, uint32_t Blue) +{ + MODIFY_REG(DMA2Dx->BGCOLR, DMA2D_BGCOLR_BLUE, Blue); +} + +/** + * @brief Return DMA2D background blue color value, expressed on 8 bits ([7:0] bits). + * @rmtoll BGCOLR BLUE LL_DMA2D_BGND_GetBlueColor + * @param DMA2Dx DMA2D Instance + * @retval Blue color value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetBlueColor(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGCOLR, DMA2D_BGCOLR_BLUE)); +} + +/** + * @brief Set DMA2D background CLUT memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll BGCMAR MA LL_DMA2D_BGND_SetCLUTMemAddr + * @param DMA2Dx DMA2D Instance + * @param CLUTMemoryAddress Value between Min_Data=0 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetCLUTMemAddr(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTMemoryAddress) +{ + LL_DMA2D_WriteReg(DMA2Dx, BGCMAR, CLUTMemoryAddress); +} + +/** + * @brief Get DMA2D background CLUT memory address, expressed on 32 bits ([31:0] bits). + * @rmtoll BGCMAR MA LL_DMA2D_BGND_GetCLUTMemAddr + * @param DMA2Dx DMA2D Instance + * @retval Background CLUT memory address value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetCLUTMemAddr(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(LL_DMA2D_ReadReg(DMA2Dx, BGCMAR)); +} + +/** + * @brief Set DMA2D background CLUT size, expressed on 8 bits ([7:0] bits). + * @rmtoll BGPFCCR CS LL_DMA2D_BGND_SetCLUTSize + * @param DMA2Dx DMA2D Instance + * @param CLUTSize Value between Min_Data=0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetCLUTSize(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTSize) +{ + MODIFY_REG(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CS, (CLUTSize << DMA2D_BGPFCCR_CS_Pos)); +} + +/** + * @brief Get DMA2D background CLUT size, expressed on 8 bits ([7:0] bits). + * @rmtoll BGPFCCR CS LL_DMA2D_BGND_GetCLUTSize + * @param DMA2Dx DMA2D Instance + * @retval Background CLUT size value between Min_Data=0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetCLUTSize(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CS) >> DMA2D_BGPFCCR_CS_Pos); +} + +/** + * @brief Set DMA2D background CLUT color mode. + * @rmtoll BGPFCCR CCM LL_DMA2D_BGND_SetCLUTColorMode + * @param DMA2Dx DMA2D Instance + * @param CLUTColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_ARGB8888 + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_RGB888 + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_BGND_SetCLUTColorMode(DMA2D_TypeDef *DMA2Dx, uint32_t CLUTColorMode) +{ + MODIFY_REG(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CCM, CLUTColorMode); +} + +/** + * @brief Return DMA2D background CLUT color mode. + * @rmtoll BGPFCCR CCM LL_DMA2D_BGND_GetCLUTColorMode + * @param DMA2Dx DMA2D Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_ARGB8888 + * @arg @ref LL_DMA2D_CLUT_COLOR_MODE_RGB888 + */ +__STATIC_INLINE uint32_t LL_DMA2D_BGND_GetCLUTColorMode(DMA2D_TypeDef *DMA2Dx) +{ + return (uint32_t)(READ_BIT(DMA2Dx->BGPFCCR, DMA2D_BGPFCCR_CCM)); +} + +/** + * @} + */ + +/** + * @} + */ + + +/** @defgroup DMA2D_LL_EF_FLAG_MANAGEMENT Flag Management + * @{ + */ + +/** + * @brief Check if the DMA2D Configuration Error Interrupt Flag is set or not + * @rmtoll ISR CEIF LL_DMA2D_IsActiveFlag_CE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_CE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_CEIF) == (DMA2D_ISR_CEIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D CLUT Transfer Complete Interrupt Flag is set or not + * @rmtoll ISR CTCIF LL_DMA2D_IsActiveFlag_CTC + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_CTC(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_CTCIF) == (DMA2D_ISR_CTCIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D CLUT Access Error Interrupt Flag is set or not + * @rmtoll ISR CAEIF LL_DMA2D_IsActiveFlag_CAE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_CAE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_CAEIF) == (DMA2D_ISR_CAEIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Watermark Interrupt Flag is set or not + * @rmtoll ISR TWIF LL_DMA2D_IsActiveFlag_TW + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_TW(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_TWIF) == (DMA2D_ISR_TWIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Complete Interrupt Flag is set or not + * @rmtoll ISR TCIF LL_DMA2D_IsActiveFlag_TC + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_TC(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_TCIF) == (DMA2D_ISR_TCIF)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Error Interrupt Flag is set or not + * @rmtoll ISR TEIF LL_DMA2D_IsActiveFlag_TE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsActiveFlag_TE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->ISR, DMA2D_ISR_TEIF) == (DMA2D_ISR_TEIF)) ? 1UL : 0UL); +} + +/** + * @brief Clear DMA2D Configuration Error Interrupt Flag + * @rmtoll IFCR CCEIF LL_DMA2D_ClearFlag_CE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_CE(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CCEIF); +} + +/** + * @brief Clear DMA2D CLUT Transfer Complete Interrupt Flag + * @rmtoll IFCR CCTCIF LL_DMA2D_ClearFlag_CTC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_CTC(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CCTCIF); +} + +/** + * @brief Clear DMA2D CLUT Access Error Interrupt Flag + * @rmtoll IFCR CAECIF LL_DMA2D_ClearFlag_CAE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_CAE(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CAECIF); +} + +/** + * @brief Clear DMA2D Transfer Watermark Interrupt Flag + * @rmtoll IFCR CTWIF LL_DMA2D_ClearFlag_TW + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_TW(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CTWIF); +} + +/** + * @brief Clear DMA2D Transfer Complete Interrupt Flag + * @rmtoll IFCR CTCIF LL_DMA2D_ClearFlag_TC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_TC(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CTCIF); +} + +/** + * @brief Clear DMA2D Transfer Error Interrupt Flag + * @rmtoll IFCR CTEIF LL_DMA2D_ClearFlag_TE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_ClearFlag_TE(DMA2D_TypeDef *DMA2Dx) +{ + WRITE_REG(DMA2Dx->IFCR, DMA2D_IFCR_CTEIF); +} + +/** + * @} + */ + +/** @defgroup DMA2D_LL_EF_IT_MANAGEMENT Interruption Management + * @{ + */ + +/** + * @brief Enable Configuration Error Interrupt + * @rmtoll CR CEIE LL_DMA2D_EnableIT_CE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_CE(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_CEIE); +} + +/** + * @brief Enable CLUT Transfer Complete Interrupt + * @rmtoll CR CTCIE LL_DMA2D_EnableIT_CTC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_CTC(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_CTCIE); +} + +/** + * @brief Enable CLUT Access Error Interrupt + * @rmtoll CR CAEIE LL_DMA2D_EnableIT_CAE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_CAE(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_CAEIE); +} + +/** + * @brief Enable Transfer Watermark Interrupt + * @rmtoll CR TWIE LL_DMA2D_EnableIT_TW + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_TW(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_TWIE); +} + +/** + * @brief Enable Transfer Complete Interrupt + * @rmtoll CR TCIE LL_DMA2D_EnableIT_TC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_TC(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_TCIE); +} + +/** + * @brief Enable Transfer Error Interrupt + * @rmtoll CR TEIE LL_DMA2D_EnableIT_TE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_EnableIT_TE(DMA2D_TypeDef *DMA2Dx) +{ + SET_BIT(DMA2Dx->CR, DMA2D_CR_TEIE); +} + +/** + * @brief Disable Configuration Error Interrupt + * @rmtoll CR CEIE LL_DMA2D_DisableIT_CE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_CE(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_CEIE); +} + +/** + * @brief Disable CLUT Transfer Complete Interrupt + * @rmtoll CR CTCIE LL_DMA2D_DisableIT_CTC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_CTC(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_CTCIE); +} + +/** + * @brief Disable CLUT Access Error Interrupt + * @rmtoll CR CAEIE LL_DMA2D_DisableIT_CAE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_CAE(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_CAEIE); +} + +/** + * @brief Disable Transfer Watermark Interrupt + * @rmtoll CR TWIE LL_DMA2D_DisableIT_TW + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_TW(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_TWIE); +} + +/** + * @brief Disable Transfer Complete Interrupt + * @rmtoll CR TCIE LL_DMA2D_DisableIT_TC + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_TC(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_TCIE); +} + +/** + * @brief Disable Transfer Error Interrupt + * @rmtoll CR TEIE LL_DMA2D_DisableIT_TE + * @param DMA2Dx DMA2D Instance + * @retval None + */ +__STATIC_INLINE void LL_DMA2D_DisableIT_TE(DMA2D_TypeDef *DMA2Dx) +{ + CLEAR_BIT(DMA2Dx->CR, DMA2D_CR_TEIE); +} + +/** + * @brief Check if the DMA2D Configuration Error interrupt source is enabled or disabled. + * @rmtoll CR CEIE LL_DMA2D_IsEnabledIT_CE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_CE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_CEIE) == (DMA2D_CR_CEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D CLUT Transfer Complete interrupt source is enabled or disabled. + * @rmtoll CR CTCIE LL_DMA2D_IsEnabledIT_CTC + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_CTC(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_CTCIE) == (DMA2D_CR_CTCIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D CLUT Access Error interrupt source is enabled or disabled. + * @rmtoll CR CAEIE LL_DMA2D_IsEnabledIT_CAE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_CAE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_CAEIE) == (DMA2D_CR_CAEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Watermark interrupt source is enabled or disabled. + * @rmtoll CR TWIE LL_DMA2D_IsEnabledIT_TW + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_TW(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_TWIE) == (DMA2D_CR_TWIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Complete interrupt source is enabled or disabled. + * @rmtoll CR TCIE LL_DMA2D_IsEnabledIT_TC + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_TC(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_TCIE) == (DMA2D_CR_TCIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if the DMA2D Transfer Error interrupt source is enabled or disabled. + * @rmtoll CR TEIE LL_DMA2D_IsEnabledIT_TE + * @param DMA2Dx DMA2D Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_DMA2D_IsEnabledIT_TE(DMA2D_TypeDef *DMA2Dx) +{ + return ((READ_BIT(DMA2Dx->CR, DMA2D_CR_TEIE) == (DMA2D_CR_TEIE)) ? 1UL : 0UL); +} + + + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup DMA2D_LL_EF_Init_Functions Initialization and De-initialization Functions + * @{ + */ + +ErrorStatus LL_DMA2D_DeInit(DMA2D_TypeDef *DMA2Dx); +ErrorStatus LL_DMA2D_Init(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_InitTypeDef *DMA2D_InitStruct); +void LL_DMA2D_StructInit(LL_DMA2D_InitTypeDef *DMA2D_InitStruct); +void LL_DMA2D_ConfigLayer(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg, uint32_t LayerIdx); +void LL_DMA2D_LayerCfgStructInit(LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg); +void LL_DMA2D_ConfigOutputColor(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_ColorTypeDef *DMA2D_ColorStruct); +uint32_t LL_DMA2D_GetOutputBlueColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode); +uint32_t LL_DMA2D_GetOutputGreenColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode); +uint32_t LL_DMA2D_GetOutputRedColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode); +uint32_t LL_DMA2D_GetOutputAlphaColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode); +void LL_DMA2D_ConfigSize(DMA2D_TypeDef *DMA2Dx, uint32_t NbrOfLines, uint32_t NbrOfPixelsPerLines); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (DMA2D) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_DMA2D_H */ diff --git a/libs/hal/stm32f4xx_ll_exti.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h similarity index 100% rename from libs/hal/stm32f4xx_ll_exti.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_exti.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h new file mode 100644 index 0000000..fe28f87 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmc.h @@ -0,0 +1,1416 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fmc.h + * @author MCD Application Team + * @brief Header file of FMC 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 STM32F4xx_LL_FMC_H +#define STM32F4xx_LL_FMC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FMC_LL + * @{ + */ + +/** @addtogroup FMC_LL_Private_Macros + * @{ + */ +#if defined(FMC_Bank1) + +#define IS_FMC_NORSRAM_BANK(__BANK__) (((__BANK__) == FMC_NORSRAM_BANK1) || \ + ((__BANK__) == FMC_NORSRAM_BANK2) || \ + ((__BANK__) == FMC_NORSRAM_BANK3) || \ + ((__BANK__) == FMC_NORSRAM_BANK4)) +#define IS_FMC_MUX(__MUX__) (((__MUX__) == FMC_DATA_ADDRESS_MUX_DISABLE) || \ + ((__MUX__) == FMC_DATA_ADDRESS_MUX_ENABLE)) +#define IS_FMC_MEMORY(__MEMORY__) (((__MEMORY__) == FMC_MEMORY_TYPE_SRAM) || \ + ((__MEMORY__) == FMC_MEMORY_TYPE_PSRAM)|| \ + ((__MEMORY__) == FMC_MEMORY_TYPE_NOR)) +#define IS_FMC_NORSRAM_MEMORY_WIDTH(__WIDTH__) (((__WIDTH__) == FMC_NORSRAM_MEM_BUS_WIDTH_8) || \ + ((__WIDTH__) == FMC_NORSRAM_MEM_BUS_WIDTH_16) || \ + ((__WIDTH__) == FMC_NORSRAM_MEM_BUS_WIDTH_32)) +#define IS_FMC_PAGESIZE(__SIZE__) (((__SIZE__) == FMC_PAGE_SIZE_NONE) || \ + ((__SIZE__) == FMC_PAGE_SIZE_128) || \ + ((__SIZE__) == FMC_PAGE_SIZE_256) || \ + ((__SIZE__) == FMC_PAGE_SIZE_512) || \ + ((__SIZE__) == FMC_PAGE_SIZE_1024)) +#if defined(FMC_BCR1_WFDIS) +#define IS_FMC_WRITE_FIFO(__FIFO__) (((__FIFO__) == FMC_WRITE_FIFO_DISABLE) || \ + ((__FIFO__) == FMC_WRITE_FIFO_ENABLE)) +#endif /* FMC_BCR1_WFDIS */ +#define IS_FMC_ACCESS_MODE(__MODE__) (((__MODE__) == FMC_ACCESS_MODE_A) || \ + ((__MODE__) == FMC_ACCESS_MODE_B) || \ + ((__MODE__) == FMC_ACCESS_MODE_C) || \ + ((__MODE__) == FMC_ACCESS_MODE_D)) +#define IS_FMC_BURSTMODE(__STATE__) (((__STATE__) == FMC_BURST_ACCESS_MODE_DISABLE) || \ + ((__STATE__) == FMC_BURST_ACCESS_MODE_ENABLE)) +#define IS_FMC_WAIT_POLARITY(__POLARITY__) (((__POLARITY__) == FMC_WAIT_SIGNAL_POLARITY_LOW) || \ + ((__POLARITY__) == FMC_WAIT_SIGNAL_POLARITY_HIGH)) +#define IS_FMC_WRAP_MODE(__MODE__) (((__MODE__) == FMC_WRAP_MODE_DISABLE) || \ + ((__MODE__) == FMC_WRAP_MODE_ENABLE)) +#define IS_FMC_WAIT_SIGNAL_ACTIVE(__ACTIVE__) (((__ACTIVE__) == FMC_WAIT_TIMING_BEFORE_WS) || \ + ((__ACTIVE__) == FMC_WAIT_TIMING_DURING_WS)) +#define IS_FMC_WRITE_OPERATION(__OPERATION__) (((__OPERATION__) == FMC_WRITE_OPERATION_DISABLE) || \ + ((__OPERATION__) == FMC_WRITE_OPERATION_ENABLE)) +#define IS_FMC_WAITE_SIGNAL(__SIGNAL__) (((__SIGNAL__) == FMC_WAIT_SIGNAL_DISABLE) || \ + ((__SIGNAL__) == FMC_WAIT_SIGNAL_ENABLE)) +#define IS_FMC_EXTENDED_MODE(__MODE__) (((__MODE__) == FMC_EXTENDED_MODE_DISABLE) || \ + ((__MODE__) == FMC_EXTENDED_MODE_ENABLE)) +#define IS_FMC_ASYNWAIT(__STATE__) (((__STATE__) == FMC_ASYNCHRONOUS_WAIT_DISABLE) || \ + ((__STATE__) == FMC_ASYNCHRONOUS_WAIT_ENABLE)) +#define IS_FMC_DATA_LATENCY(__LATENCY__) (((__LATENCY__) > 1U) && ((__LATENCY__) <= 17U)) +#define IS_FMC_WRITE_BURST(__BURST__) (((__BURST__) == FMC_WRITE_BURST_DISABLE) || \ + ((__BURST__) == FMC_WRITE_BURST_ENABLE)) +#define IS_FMC_CONTINOUS_CLOCK(__CCLOCK__) (((__CCLOCK__) == FMC_CONTINUOUS_CLOCK_SYNC_ONLY) || \ + ((__CCLOCK__) == FMC_CONTINUOUS_CLOCK_SYNC_ASYNC)) +#define IS_FMC_ADDRESS_SETUP_TIME(__TIME__) ((__TIME__) <= 15U) +#define IS_FMC_ADDRESS_HOLD_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 15U)) +#define IS_FMC_DATASETUP_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 255U)) +#define IS_FMC_DATAHOLD_DURATION(__DATAHOLD__) ((__DATAHOLD__) <= 3U) +#define IS_FMC_TURNAROUND_TIME(__TIME__) ((__TIME__) <= 15U) +#define IS_FMC_CLK_DIV(__DIV__) (((__DIV__) > 1U) && ((__DIV__) <= 16U)) +#define IS_FMC_NORSRAM_DEVICE(__INSTANCE__) ((__INSTANCE__) == FMC_NORSRAM_DEVICE) +#define IS_FMC_NORSRAM_EXTENDED_DEVICE(__INSTANCE__) ((__INSTANCE__) == FMC_NORSRAM_EXTENDED_DEVICE) + +#endif /* FMC_Bank1 */ +#if (defined(FMC_Bank3) || defined(FMC_Bank2_3)) + +#if defined(FMC_Bank2_3) +#define IS_FMC_NAND_BANK(__BANK__) (((__BANK__) == FMC_NAND_BANK2) || \ + ((__BANK__) == FMC_NAND_BANK3)) +#else +#define IS_FMC_NAND_BANK(__BANK__) ((__BANK__) == FMC_NAND_BANK3) +#endif /* FMC_Bank2_3 */ +#define IS_FMC_WAIT_FEATURE(__FEATURE__) (((__FEATURE__) == FMC_NAND_PCC_WAIT_FEATURE_DISABLE) || \ + ((__FEATURE__) == FMC_NAND_PCC_WAIT_FEATURE_ENABLE)) +#define IS_FMC_NAND_MEMORY_WIDTH(__WIDTH__) (((__WIDTH__) == FMC_NAND_PCC_MEM_BUS_WIDTH_8) || \ + ((__WIDTH__) == FMC_NAND_PCC_MEM_BUS_WIDTH_16)) +#define IS_FMC_ECC_STATE(__STATE__) (((__STATE__) == FMC_NAND_ECC_DISABLE) || \ + ((__STATE__) == FMC_NAND_ECC_ENABLE)) + +#define IS_FMC_ECCPAGE_SIZE(__SIZE__) (((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_256BYTE) || \ + ((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_512BYTE) || \ + ((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_1024BYTE) || \ + ((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_2048BYTE) || \ + ((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_4096BYTE) || \ + ((__SIZE__) == FMC_NAND_ECC_PAGE_SIZE_8192BYTE)) +#define IS_FMC_TCLR_TIME(__TIME__) ((__TIME__) <= 255U) +#define IS_FMC_TAR_TIME(__TIME__) ((__TIME__) <= 255U) +#define IS_FMC_SETUP_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FMC_WAIT_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FMC_HOLD_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FMC_HIZ_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FMC_NAND_DEVICE(__INSTANCE__) ((__INSTANCE__) == FMC_NAND_DEVICE) + +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ +#if defined(FMC_Bank4) +#define IS_FMC_PCCARD_DEVICE(__INSTANCE__) ((__INSTANCE__) == FMC_PCCARD_DEVICE) + +#endif /* FMC_Bank4 */ +#if defined(FMC_Bank5_6) + +#define IS_FMC_SDMEMORY_WIDTH(__WIDTH__) (((__WIDTH__) == FMC_SDRAM_MEM_BUS_WIDTH_8) || \ + ((__WIDTH__) == FMC_SDRAM_MEM_BUS_WIDTH_16) || \ + ((__WIDTH__) == FMC_SDRAM_MEM_BUS_WIDTH_32)) +#define IS_FMC_WRITE_PROTECTION(__WRITE__) (((__WRITE__) == FMC_SDRAM_WRITE_PROTECTION_DISABLE) || \ + ((__WRITE__) == FMC_SDRAM_WRITE_PROTECTION_ENABLE)) +#define IS_FMC_SDCLOCK_PERIOD(__PERIOD__) (((__PERIOD__) == FMC_SDRAM_CLOCK_DISABLE) || \ + ((__PERIOD__) == FMC_SDRAM_CLOCK_PERIOD_2) || \ + ((__PERIOD__) == FMC_SDRAM_CLOCK_PERIOD_3)) +#define IS_FMC_READ_BURST(__RBURST__) (((__RBURST__) == FMC_SDRAM_RBURST_DISABLE) || \ + ((__RBURST__) == FMC_SDRAM_RBURST_ENABLE)) +#define IS_FMC_READPIPE_DELAY(__DELAY__) (((__DELAY__) == FMC_SDRAM_RPIPE_DELAY_0) || \ + ((__DELAY__) == FMC_SDRAM_RPIPE_DELAY_1) || \ + ((__DELAY__) == FMC_SDRAM_RPIPE_DELAY_2)) +#define IS_FMC_COMMAND_MODE(__COMMAND__) (((__COMMAND__) == FMC_SDRAM_CMD_NORMAL_MODE) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_CLK_ENABLE) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_PALL) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_AUTOREFRESH_MODE) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_LOAD_MODE) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_SELFREFRESH_MODE) || \ + ((__COMMAND__) == FMC_SDRAM_CMD_POWERDOWN_MODE)) +#define IS_FMC_COMMAND_TARGET(__TARGET__) (((__TARGET__) == FMC_SDRAM_CMD_TARGET_BANK1) || \ + ((__TARGET__) == FMC_SDRAM_CMD_TARGET_BANK2) || \ + ((__TARGET__) == FMC_SDRAM_CMD_TARGET_BANK1_2)) +#define IS_FMC_LOADTOACTIVE_DELAY(__DELAY__) (((__DELAY__) > 0U) && ((__DELAY__) <= 16U)) +#define IS_FMC_EXITSELFREFRESH_DELAY(__DELAY__) (((__DELAY__) > 0U) && ((__DELAY__) <= 16U)) +#define IS_FMC_SELFREFRESH_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 16U)) +#define IS_FMC_ROWCYCLE_DELAY(__DELAY__) (((__DELAY__) > 0U) && ((__DELAY__) <= 16U)) +#define IS_FMC_WRITE_RECOVERY_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 16U)) +#define IS_FMC_RP_DELAY(__DELAY__) (((__DELAY__) > 0U) && ((__DELAY__) <= 16U)) +#define IS_FMC_RCD_DELAY(__DELAY__) (((__DELAY__) > 0U) && ((__DELAY__) <= 16U)) +#define IS_FMC_AUTOREFRESH_NUMBER(__NUMBER__) (((__NUMBER__) > 0U) && ((__NUMBER__) <= 15U)) +#define IS_FMC_MODE_REGISTER(__CONTENT__) ((__CONTENT__) <= 8191U) +#define IS_FMC_REFRESH_RATE(__RATE__) ((__RATE__) <= 8191U) +#define IS_FMC_SDRAM_DEVICE(__INSTANCE__) ((__INSTANCE__) == FMC_SDRAM_DEVICE) +#define IS_FMC_SDRAM_BANK(__BANK__) (((__BANK__) == FMC_SDRAM_BANK1) || \ + ((__BANK__) == FMC_SDRAM_BANK2)) +#define IS_FMC_COLUMNBITS_NUMBER(__COLUMN__) (((__COLUMN__) == FMC_SDRAM_COLUMN_BITS_NUM_8) || \ + ((__COLUMN__) == FMC_SDRAM_COLUMN_BITS_NUM_9) || \ + ((__COLUMN__) == FMC_SDRAM_COLUMN_BITS_NUM_10) || \ + ((__COLUMN__) == FMC_SDRAM_COLUMN_BITS_NUM_11)) +#define IS_FMC_ROWBITS_NUMBER(__ROW__) (((__ROW__) == FMC_SDRAM_ROW_BITS_NUM_11) || \ + ((__ROW__) == FMC_SDRAM_ROW_BITS_NUM_12) || \ + ((__ROW__) == FMC_SDRAM_ROW_BITS_NUM_13)) +#define IS_FMC_INTERNALBANK_NUMBER(__NUMBER__) (((__NUMBER__) == FMC_SDRAM_INTERN_BANKS_NUM_2) || \ + ((__NUMBER__) == FMC_SDRAM_INTERN_BANKS_NUM_4)) +#define IS_FMC_CAS_LATENCY(__LATENCY__) (((__LATENCY__) == FMC_SDRAM_CAS_LATENCY_1) || \ + ((__LATENCY__) == FMC_SDRAM_CAS_LATENCY_2) || \ + ((__LATENCY__) == FMC_SDRAM_CAS_LATENCY_3)) + +#endif /* FMC_Bank5_6 */ + +/** + * @} + */ + +/* Exported typedef ----------------------------------------------------------*/ + +/** @defgroup FMC_LL_Exported_typedef FMC Low Layer Exported Types + * @{ + */ + +#if defined(FMC_Bank1) +#define FMC_NORSRAM_TypeDef FMC_Bank1_TypeDef +#define FMC_NORSRAM_EXTENDED_TypeDef FMC_Bank1E_TypeDef +#endif /* FMC_Bank1 */ +#if defined(FMC_Bank2_3) +#define FMC_NAND_TypeDef FMC_Bank2_3_TypeDef +#else +#define FMC_NAND_TypeDef FMC_Bank3_TypeDef +#endif /* FMC_Bank2_3 */ +#if defined(FMC_Bank4) +#define FMC_PCCARD_TypeDef FMC_Bank4_TypeDef +#endif /* FMC_Bank4 */ +#if defined(FMC_Bank5_6) +#define FMC_SDRAM_TypeDef FMC_Bank5_6_TypeDef +#endif /* FMC_Bank5_6 */ + +#if defined(FMC_Bank1) +#define FMC_NORSRAM_DEVICE FMC_Bank1 +#define FMC_NORSRAM_EXTENDED_DEVICE FMC_Bank1E +#endif /* FMC_Bank1 */ +#if defined(FMC_Bank2_3) +#define FMC_NAND_DEVICE FMC_Bank2_3 +#else +#define FMC_NAND_DEVICE FMC_Bank3 +#endif /* FMC_Bank2_3 */ +#if defined(FMC_Bank4) +#define FMC_PCCARD_DEVICE FMC_Bank4 +#endif /* FMC_Bank4 */ +#if defined(FMC_Bank5_6) +#define FMC_SDRAM_DEVICE FMC_Bank5_6 +#endif /* FMC_Bank5_6 */ + +#if defined(FMC_Bank1) +/** + * @brief FMC NORSRAM Configuration Structure definition + */ +typedef struct +{ + uint32_t NSBank; /*!< Specifies the NORSRAM memory device that will be used. + This parameter can be a value of @ref FMC_NORSRAM_Bank */ + + uint32_t DataAddressMux; /*!< Specifies whether the address and data values are + multiplexed on the data bus or not. + This parameter can be a value of @ref FMC_Data_Address_Bus_Multiplexing */ + + uint32_t MemoryType; /*!< Specifies the type of external memory attached to + the corresponding memory device. + This parameter can be a value of @ref FMC_Memory_Type */ + + uint32_t MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be a value of @ref FMC_NORSRAM_Data_Width */ + + uint32_t BurstAccessMode; /*!< Enables or disables the burst access mode for Flash memory, + valid only with synchronous burst Flash memories. + This parameter can be a value of @ref FMC_Burst_Access_Mode */ + + uint32_t WaitSignalPolarity; /*!< Specifies the wait signal polarity, valid only when accessing + the Flash memory in burst mode. + This parameter can be a value of @ref FMC_Wait_Signal_Polarity */ + + uint32_t WrapMode; /*!< Enables or disables the Wrapped burst access mode for Flash + memory, valid only when accessing Flash memories in burst mode. + This parameter can be a value of @ref FMC_Wrap_Mode + This mode is not available for the STM32F446/467/479xx devices */ + + uint32_t WaitSignalActive; /*!< Specifies if the wait signal is asserted by the memory one + clock cycle before the wait state or during the wait state, + valid only when accessing memories in burst mode. + This parameter can be a value of @ref FMC_Wait_Timing */ + + uint32_t WriteOperation; /*!< Enables or disables the write operation in the selected device by the FMC. + This parameter can be a value of @ref FMC_Write_Operation */ + + uint32_t WaitSignal; /*!< Enables or disables the wait state insertion via wait + signal, valid for Flash memory access in burst mode. + This parameter can be a value of @ref FMC_Wait_Signal */ + + uint32_t ExtendedMode; /*!< Enables or disables the extended mode. + This parameter can be a value of @ref FMC_Extended_Mode */ + + uint32_t AsynchronousWait; /*!< Enables or disables wait signal during asynchronous transfers, + valid only with asynchronous Flash memories. + This parameter can be a value of @ref FMC_AsynchronousWait */ + + uint32_t WriteBurst; /*!< Enables or disables the write burst operation. + This parameter can be a value of @ref FMC_Write_Burst */ + + uint32_t ContinuousClock; /*!< Enables or disables the FMC clock output to external memory devices. + This parameter is only enabled through the FMC_BCR1 register, + and don't care through FMC_BCR2..4 registers. + This parameter can be a value of @ref FMC_Continous_Clock */ + + uint32_t WriteFifo; /*!< Enables or disables the write FIFO used by the FMC controller. + This parameter is only enabled through the FMC_BCR1 register, + and don't care through FMC_BCR2..4 registers. + This parameter can be a value of @ref FMC_Write_FIFO + This mode is available only for the STM32F446/469/479xx devices */ + + uint32_t PageSize; /*!< Specifies the memory page size. + This parameter can be a value of @ref FMC_Page_Size */ +} FMC_NORSRAM_InitTypeDef; + +/** + * @brief FMC NORSRAM Timing parameters structure definition + */ +typedef struct +{ + uint32_t AddressSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address setup time. + This parameter can be a value between Min_Data = 0 and Max_Data = 15. + @note This parameter is not used with synchronous NOR Flash memories. */ + + uint32_t AddressHoldTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address hold time. + This parameter can be a value between Min_Data = 1 and Max_Data = 15. + @note This parameter is not used with synchronous NOR Flash memories. */ + + uint32_t DataSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the data setup time. + This parameter can be a value between Min_Data = 1 and Max_Data = 255. + @note This parameter is used for SRAMs, ROMs and asynchronous multiplexed + NOR Flash memories. */ + + uint32_t BusTurnAroundDuration; /*!< Defines the number of HCLK cycles to configure + the duration of the bus turnaround. + This parameter can be a value between Min_Data = 0 and Max_Data = 15. + @note This parameter is only used for multiplexed NOR Flash memories. */ + + uint32_t CLKDivision; /*!< Defines the period of CLK clock output signal, expressed in number of + HCLK cycles. This parameter can be a value between Min_Data = 2 and + Max_Data = 16. + @note This parameter is not used for asynchronous NOR Flash, SRAM or ROM + accesses. */ + + uint32_t DataLatency; /*!< Defines the number of memory clock cycles to issue + to the memory before getting the first data. + The parameter value depends on the memory type as shown below: + - It must be set to 0 in case of a CRAM + - It is don't care in asynchronous NOR, SRAM or ROM accesses + - It may assume a value between Min_Data = 2 and Max_Data = 17 + in NOR Flash memories with synchronous burst mode enable */ + + uint32_t AccessMode; /*!< Specifies the asynchronous access mode. + This parameter can be a value of @ref FMC_Access_Mode */ +} FMC_NORSRAM_TimingTypeDef; +#endif /* FMC_Bank1 */ + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) +/** + * @brief FMC NAND Configuration Structure definition + */ +typedef struct +{ + uint32_t NandBank; /*!< Specifies the NAND memory device that will be used. + This parameter can be a value of @ref FMC_NAND_Bank */ + + uint32_t Waitfeature; /*!< Enables or disables the Wait feature for the NAND Memory device. + This parameter can be any value of @ref FMC_Wait_feature */ + + uint32_t MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be any value of @ref FMC_NAND_Data_Width */ + + uint32_t EccComputation; /*!< Enables or disables the ECC computation. + This parameter can be any value of @ref FMC_ECC */ + + uint32_t ECCPageSize; /*!< Defines the page size for the extended ECC. + This parameter can be any value of @ref FMC_ECC_Page_Size */ + + uint32_t TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between Min_Data = 0 and Max_Data = 255 */ + + uint32_t TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between Min_Data = 0 and Max_Data = 255 */ +} FMC_NAND_InitTypeDef; +#endif + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FMC_Bank4) +/** + * @brief FMC NAND Timing parameters structure definition + */ +typedef struct +{ + uint32_t SetupTime; /*!< Defines the number of HCLK cycles to setup address before + the command assertion for NAND-Flash read or write access + to common/Attribute or I/O memory space (depending on + the memory space timing to be configured). + This parameter can be a value between Min_Data = 0 and Max_Data = 254 */ + + uint32_t WaitSetupTime; /*!< Defines the minimum number of HCLK cycles to assert the + command for NAND-Flash read or write access to + common/Attribute or I/O memory space (depending on the + memory space timing to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ + + uint32_t HoldSetupTime; /*!< Defines the number of HCLK clock cycles to hold address + (and data for write access) after the command de-assertion + for NAND-Flash read or write access to common/Attribute + or I/O memory space (depending on the memory space timing + to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ + + uint32_t HiZSetupTime; /*!< Defines the number of HCLK clock cycles during which the + data bus is kept in HiZ after the start of a NAND-Flash + write access to common/Attribute or I/O memory space (depending + on the memory space timing to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ +} FMC_NAND_PCC_TimingTypeDef; +#endif /* FMC_Bank3 || FMC_Bank2_3 */ + +#if defined(FMC_Bank4) +/** + * @brief FMC PCCARD Configuration Structure definition + */ +typedef struct +{ + uint32_t Waitfeature; /*!< Enables or disables the Wait feature for the PCCARD Memory device. + This parameter can be any value of @ref FMC_Wait_feature */ + + uint32_t TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between Min_Data = 0 and Max_Data = 255 */ + + uint32_t TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between Min_Data = 0 and Max_Data = 255 */ +}FMC_PCCARD_InitTypeDef; +#endif /* FMC_Bank4 */ + +#if defined(FMC_Bank5_6) +/** + * @brief FMC SDRAM Configuration Structure definition + */ +typedef struct +{ + uint32_t SDBank; /*!< Specifies the SDRAM memory device that will be used. + This parameter can be a value of @ref FMC_SDRAM_Bank */ + + uint32_t ColumnBitsNumber; /*!< Defines the number of bits of column address. + This parameter can be a value of @ref FMC_SDRAM_Column_Bits_number. */ + + uint32_t RowBitsNumber; /*!< Defines the number of bits of column address. + This parameter can be a value of @ref FMC_SDRAM_Row_Bits_number. */ + + uint32_t MemoryDataWidth; /*!< Defines the memory device width. + This parameter can be a value of @ref FMC_SDRAM_Memory_Bus_Width. */ + + uint32_t InternalBankNumber; /*!< Defines the number of the device's internal banks. + This parameter can be of @ref FMC_SDRAM_Internal_Banks_Number. */ + + uint32_t CASLatency; /*!< Defines the SDRAM CAS latency in number of memory clock cycles. + This parameter can be a value of @ref FMC_SDRAM_CAS_Latency. */ + + uint32_t WriteProtection; /*!< Enables the SDRAM device to be accessed in write mode. + This parameter can be a value of @ref FMC_SDRAM_Write_Protection. */ + + uint32_t SDClockPeriod; /*!< Define the SDRAM Clock Period for both SDRAM devices and they allow + to disable the clock before changing frequency. + This parameter can be a value of @ref FMC_SDRAM_Clock_Period. */ + + uint32_t ReadBurst; /*!< This bit enable the SDRAM controller to anticipate the next read + commands during the CAS latency and stores data in the Read FIFO. + This parameter can be a value of @ref FMC_SDRAM_Read_Burst. */ + + uint32_t ReadPipeDelay; /*!< Define the delay in system clock cycles on read data path. + This parameter can be a value of @ref FMC_SDRAM_Read_Pipe_Delay. */ +} FMC_SDRAM_InitTypeDef; + +/** + * @brief FMC SDRAM Timing parameters structure definition + */ +typedef struct +{ + uint32_t LoadToActiveDelay; /*!< Defines the delay between a Load Mode Register command and + an active or Refresh command in number of memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t ExitSelfRefreshDelay; /*!< Defines the delay from releasing the self refresh command to + issuing the Activate command in number of memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t SelfRefreshTime; /*!< Defines the minimum Self Refresh period in number of memory clock + cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t RowCycleDelay; /*!< Defines the delay between the Refresh command and the Activate command + and the delay between two consecutive Refresh commands in number of + memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t WriteRecoveryTime; /*!< Defines the Write recovery Time in number of memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t RPDelay; /*!< Defines the delay between a Precharge Command and an other command + in number of memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ + + uint32_t RCDDelay; /*!< Defines the delay between the Activate Command and a Read/Write + command in number of memory clock cycles. + This parameter can be a value between Min_Data = 1 and Max_Data = 16 */ +} FMC_SDRAM_TimingTypeDef; + +/** + * @brief SDRAM command parameters structure definition + */ +typedef struct +{ + uint32_t CommandMode; /*!< Defines the command issued to the SDRAM device. + This parameter can be a value of @ref FMC_SDRAM_Command_Mode. */ + + uint32_t CommandTarget; /*!< Defines which device (1 or 2) the command will be issued to. + This parameter can be a value of @ref FMC_SDRAM_Command_Target. */ + + uint32_t AutoRefreshNumber; /*!< Defines the number of consecutive auto refresh command issued + in auto refresh mode. + This parameter can be a value between Min_Data = 1 and Max_Data = 15 */ + + uint32_t ModeRegisterDefinition; /*!< Defines the SDRAM Mode register content */ +} FMC_SDRAM_CommandTypeDef; +#endif /* FMC_Bank5_6 */ +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @addtogroup FMC_LL_Exported_Constants FMC Low Layer Exported Constants + * @{ + */ +#if defined(FMC_Bank1) + +/** @defgroup FMC_LL_NOR_SRAM_Controller FMC NOR/SRAM Controller + * @{ + */ + +/** @defgroup FMC_NORSRAM_Bank FMC NOR/SRAM Bank + * @{ + */ +#define FMC_NORSRAM_BANK1 (0x00000000U) +#define FMC_NORSRAM_BANK2 (0x00000002U) +#define FMC_NORSRAM_BANK3 (0x00000004U) +#define FMC_NORSRAM_BANK4 (0x00000006U) +/** + * @} + */ + +/** @defgroup FMC_Data_Address_Bus_Multiplexing FMC Data Address Bus Multiplexing + * @{ + */ +#define FMC_DATA_ADDRESS_MUX_DISABLE (0x00000000U) +#define FMC_DATA_ADDRESS_MUX_ENABLE (0x00000002U) +/** + * @} + */ + +/** @defgroup FMC_Memory_Type FMC Memory Type + * @{ + */ +#define FMC_MEMORY_TYPE_SRAM (0x00000000U) +#define FMC_MEMORY_TYPE_PSRAM (0x00000004U) +#define FMC_MEMORY_TYPE_NOR (0x00000008U) +/** + * @} + */ + +/** @defgroup FMC_NORSRAM_Data_Width FMC NORSRAM Data Width + * @{ + */ +#define FMC_NORSRAM_MEM_BUS_WIDTH_8 (0x00000000U) +#define FMC_NORSRAM_MEM_BUS_WIDTH_16 (0x00000010U) +#define FMC_NORSRAM_MEM_BUS_WIDTH_32 (0x00000020U) +/** + * @} + */ + +/** @defgroup FMC_NORSRAM_Flash_Access FMC NOR/SRAM Flash Access + * @{ + */ +#define FMC_NORSRAM_FLASH_ACCESS_ENABLE (0x00000040U) +#define FMC_NORSRAM_FLASH_ACCESS_DISABLE (0x00000000U) +/** + * @} + */ + +/** @defgroup FMC_Burst_Access_Mode FMC Burst Access Mode + * @{ + */ +#define FMC_BURST_ACCESS_MODE_DISABLE (0x00000000U) +#define FMC_BURST_ACCESS_MODE_ENABLE (0x00000100U) +/** + * @} + */ + +/** @defgroup FMC_Wait_Signal_Polarity FMC Wait Signal Polarity + * @{ + */ +#define FMC_WAIT_SIGNAL_POLARITY_LOW (0x00000000U) +#define FMC_WAIT_SIGNAL_POLARITY_HIGH (0x00000200U) +/** + * @} + */ + +/** @defgroup FMC_Wrap_Mode FMC Wrap Mode + * @note This mode is not available for the STM32F446/469/479xx devices + * @{ + */ +#define FMC_WRAP_MODE_DISABLE (0x00000000U) +#define FMC_WRAP_MODE_ENABLE (0x00000400U) +/** + * @} + */ + +/** @defgroup FMC_Wait_Timing FMC Wait Timing + * @{ + */ +#define FMC_WAIT_TIMING_BEFORE_WS (0x00000000U) +#define FMC_WAIT_TIMING_DURING_WS (0x00000800U) +/** + * @} + */ + +/** @defgroup FMC_Write_Operation FMC Write Operation + * @{ + */ +#define FMC_WRITE_OPERATION_DISABLE (0x00000000U) +#define FMC_WRITE_OPERATION_ENABLE (0x00001000U) +/** + * @} + */ + +/** @defgroup FMC_Wait_Signal FMC Wait Signal + * @{ + */ +#define FMC_WAIT_SIGNAL_DISABLE (0x00000000U) +#define FMC_WAIT_SIGNAL_ENABLE (0x00002000U) +/** + * @} + */ + +/** @defgroup FMC_Extended_Mode FMC Extended Mode + * @{ + */ +#define FMC_EXTENDED_MODE_DISABLE (0x00000000U) +#define FMC_EXTENDED_MODE_ENABLE (0x00004000U) +/** + * @} + */ + +/** @defgroup FMC_AsynchronousWait FMC Asynchronous Wait + * @{ + */ +#define FMC_ASYNCHRONOUS_WAIT_DISABLE (0x00000000U) +#define FMC_ASYNCHRONOUS_WAIT_ENABLE (0x00008000U) +/** + * @} + */ + +/** @defgroup FMC_Page_Size FMC Page Size + * @{ + */ +#define FMC_PAGE_SIZE_NONE (0x00000000U) +#define FMC_PAGE_SIZE_128 FMC_BCR1_CPSIZE_0 +#define FMC_PAGE_SIZE_256 FMC_BCR1_CPSIZE_1 +#define FMC_PAGE_SIZE_512 (FMC_BCR1_CPSIZE_0\ + | FMC_BCR1_CPSIZE_1) +#define FMC_PAGE_SIZE_1024 FMC_BCR1_CPSIZE_2 +/** + * @} + */ + +/** @defgroup FMC_Write_Burst FMC Write Burst + * @{ + */ +#define FMC_WRITE_BURST_DISABLE (0x00000000U) +#define FMC_WRITE_BURST_ENABLE (0x00080000U) +/** + * @} + */ + +/** @defgroup FMC_Continous_Clock FMC Continuous Clock + * @{ + */ +#define FMC_CONTINUOUS_CLOCK_SYNC_ONLY (0x00000000U) +#define FMC_CONTINUOUS_CLOCK_SYNC_ASYNC (0x00100000U) +/** + * @} + */ + +#if defined(FMC_BCR1_WFDIS) +/** @defgroup FMC_Write_FIFO FMC Write FIFO + * @note These values are available only for the STM32F446/469/479xx devices. + * @{ + */ +#define FMC_WRITE_FIFO_DISABLE FMC_BCR1_WFDIS +#define FMC_WRITE_FIFO_ENABLE (0x00000000U) +#endif /* FMC_BCR1_WFDIS */ +/** + * @} + */ + +/** @defgroup FMC_Access_Mode FMC Access Mode + * @{ + */ +#define FMC_ACCESS_MODE_A (0x00000000U) +#define FMC_ACCESS_MODE_B (0x10000000U) +#define FMC_ACCESS_MODE_C (0x20000000U) +#define FMC_ACCESS_MODE_D (0x30000000U) +/** + * @} + */ + +/** + * @} + */ +#endif /* FMC_Bank1 */ + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FMC_Bank4) + +/** @defgroup FMC_LL_NAND_Controller FMC NAND Controller + * @{ + */ +/** @defgroup FMC_NAND_Bank FMC NAND Bank + * @{ + */ +#if defined(FMC_Bank2_3) +#define FMC_NAND_BANK2 (0x00000010U) +#endif +#define FMC_NAND_BANK3 (0x00000100U) +/** + * @} + */ + +/** @defgroup FMC_Wait_feature FMC Wait feature + * @{ + */ +#define FMC_NAND_PCC_WAIT_FEATURE_DISABLE (0x00000000U) +#define FMC_NAND_PCC_WAIT_FEATURE_ENABLE (0x00000002U) +/** + * @} + */ + +/** @defgroup FMC_PCR_Memory_Type FMC PCR Memory Type + * @{ + */ +#if defined(FMC_Bank4) +#define FMC_PCR_MEMORY_TYPE_PCCARD (0x00000000U) +#endif /* FMC_Bank4 */ +#define FMC_PCR_MEMORY_TYPE_NAND (0x00000008U) +/** + * @} + */ + +/** @defgroup FMC_NAND_Data_Width FMC NAND Data Width + * @{ + */ +#define FMC_NAND_PCC_MEM_BUS_WIDTH_8 (0x00000000U) +#define FMC_NAND_PCC_MEM_BUS_WIDTH_16 (0x00000010U) +/** + * @} + */ + +/** @defgroup FMC_ECC FMC ECC + * @{ + */ +#define FMC_NAND_ECC_DISABLE (0x00000000U) +#define FMC_NAND_ECC_ENABLE (0x00000040U) +/** + * @} + */ + +/** @defgroup FMC_ECC_Page_Size FMC ECC Page Size + * @{ + */ +#define FMC_NAND_ECC_PAGE_SIZE_256BYTE (0x00000000U) +#define FMC_NAND_ECC_PAGE_SIZE_512BYTE (0x00020000U) +#define FMC_NAND_ECC_PAGE_SIZE_1024BYTE (0x00040000U) +#define FMC_NAND_ECC_PAGE_SIZE_2048BYTE (0x00060000U) +#define FMC_NAND_ECC_PAGE_SIZE_4096BYTE (0x00080000U) +#define FMC_NAND_ECC_PAGE_SIZE_8192BYTE (0x000A0000U) +/** + * @} + */ + +/** + * @} + */ +#endif /* FMC_Bank3 || FMC_Bank2_3 || FMC_Bank4 */ + +#if defined(FMC_Bank5_6) +/** @defgroup FMC_LL_SDRAM_Controller FMC SDRAM Controller + * @{ + */ +/** @defgroup FMC_SDRAM_Bank FMC SDRAM Bank + * @{ + */ +#define FMC_SDRAM_BANK1 (0x00000000U) +#define FMC_SDRAM_BANK2 (0x00000001U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Column_Bits_number FMC SDRAM Column Bits number + * @{ + */ +#define FMC_SDRAM_COLUMN_BITS_NUM_8 (0x00000000U) +#define FMC_SDRAM_COLUMN_BITS_NUM_9 (0x00000001U) +#define FMC_SDRAM_COLUMN_BITS_NUM_10 (0x00000002U) +#define FMC_SDRAM_COLUMN_BITS_NUM_11 (0x00000003U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Row_Bits_number FMC SDRAM Row Bits number + * @{ + */ +#define FMC_SDRAM_ROW_BITS_NUM_11 (0x00000000U) +#define FMC_SDRAM_ROW_BITS_NUM_12 (0x00000004U) +#define FMC_SDRAM_ROW_BITS_NUM_13 (0x00000008U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Memory_Bus_Width FMC SDRAM Memory Bus Width + * @{ + */ +#define FMC_SDRAM_MEM_BUS_WIDTH_8 (0x00000000U) +#define FMC_SDRAM_MEM_BUS_WIDTH_16 (0x00000010U) +#define FMC_SDRAM_MEM_BUS_WIDTH_32 (0x00000020U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Internal_Banks_Number FMC SDRAM Internal Banks Number + * @{ + */ +#define FMC_SDRAM_INTERN_BANKS_NUM_2 (0x00000000U) +#define FMC_SDRAM_INTERN_BANKS_NUM_4 (0x00000040U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_CAS_Latency FMC SDRAM CAS Latency + * @{ + */ +#define FMC_SDRAM_CAS_LATENCY_1 (0x00000080U) +#define FMC_SDRAM_CAS_LATENCY_2 (0x00000100U) +#define FMC_SDRAM_CAS_LATENCY_3 (0x00000180U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Write_Protection FMC SDRAM Write Protection + * @{ + */ +#define FMC_SDRAM_WRITE_PROTECTION_DISABLE (0x00000000U) +#define FMC_SDRAM_WRITE_PROTECTION_ENABLE (0x00000200U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Clock_Period FMC SDRAM Clock Period + * @{ + */ +#define FMC_SDRAM_CLOCK_DISABLE (0x00000000U) +#define FMC_SDRAM_CLOCK_PERIOD_2 (0x00000800U) +#define FMC_SDRAM_CLOCK_PERIOD_3 (0x00000C00U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Read_Burst FMC SDRAM Read Burst + * @{ + */ +#define FMC_SDRAM_RBURST_DISABLE (0x00000000U) +#define FMC_SDRAM_RBURST_ENABLE (0x00001000U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Read_Pipe_Delay FMC SDRAM Read Pipe Delay + * @{ + */ +#define FMC_SDRAM_RPIPE_DELAY_0 (0x00000000U) +#define FMC_SDRAM_RPIPE_DELAY_1 (0x00002000U) +#define FMC_SDRAM_RPIPE_DELAY_2 (0x00004000U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Command_Mode FMC SDRAM Command Mode + * @{ + */ +#define FMC_SDRAM_CMD_NORMAL_MODE (0x00000000U) +#define FMC_SDRAM_CMD_CLK_ENABLE (0x00000001U) +#define FMC_SDRAM_CMD_PALL (0x00000002U) +#define FMC_SDRAM_CMD_AUTOREFRESH_MODE (0x00000003U) +#define FMC_SDRAM_CMD_LOAD_MODE (0x00000004U) +#define FMC_SDRAM_CMD_SELFREFRESH_MODE (0x00000005U) +#define FMC_SDRAM_CMD_POWERDOWN_MODE (0x00000006U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Command_Target FMC SDRAM Command Target + * @{ + */ +#define FMC_SDRAM_CMD_TARGET_BANK2 FMC_SDCMR_CTB2 +#define FMC_SDRAM_CMD_TARGET_BANK1 FMC_SDCMR_CTB1 +#define FMC_SDRAM_CMD_TARGET_BANK1_2 (0x00000018U) +/** + * @} + */ + +/** @defgroup FMC_SDRAM_Mode_Status FMC SDRAM Mode Status + * @{ + */ +#define FMC_SDRAM_NORMAL_MODE (0x00000000U) +#define FMC_SDRAM_SELF_REFRESH_MODE FMC_SDSR_MODES1_0 +#define FMC_SDRAM_POWER_DOWN_MODE FMC_SDSR_MODES1_1 +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank5_6 */ + +/** @defgroup FMC_LL_Interrupt_definition FMC Low Layer Interrupt definition + * @{ + */ +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FMC_Bank4) +#define FMC_IT_RISING_EDGE (0x00000008U) +#define FMC_IT_LEVEL (0x00000010U) +#define FMC_IT_FALLING_EDGE (0x00000020U) +#endif /* FMC_Bank3 || FMC_Bank2_3 || FMC_Bank4 */ +#if defined(FMC_Bank5_6) +#define FMC_IT_REFRESH_ERROR (0x00004000U) +#endif /* FMC_Bank5_6 */ +/** + * @} + */ + +/** @defgroup FMC_LL_Flag_definition FMC Low Layer Flag definition + * @{ + */ +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FMC_Bank4) +#define FMC_FLAG_RISING_EDGE (0x00000001U) +#define FMC_FLAG_LEVEL (0x00000002U) +#define FMC_FLAG_FALLING_EDGE (0x00000004U) +#define FMC_FLAG_FEMPT (0x00000040U) +#endif /* FMC_Bank3 || FMC_Bank2_3 || FMC_Bank4 */ +#if defined(FMC_Bank5_6) +#define FMC_SDRAM_FLAG_REFRESH_IT FMC_SDSR_RE +#define FMC_SDRAM_FLAG_BUSY FMC_SDSR_BUSY +#define FMC_SDRAM_FLAG_REFRESH_ERROR FMC_SDRTR_CRE +#endif /* FMC_Bank5_6 */ +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup FMC_LL_Private_Macros FMC_LL Private Macros + * @{ + */ +#if defined(FMC_Bank1) +/** @defgroup FMC_LL_NOR_Macros FMC NOR/SRAM Macros + * @brief macros to handle NOR device enable/disable and read/write operations + * @{ + */ + +/** + * @brief Enable the NORSRAM device access. + * @param __INSTANCE__ FMC_NORSRAM Instance + * @param __BANK__ FMC_NORSRAM Bank + * @retval None + */ +#define __FMC_NORSRAM_ENABLE(__INSTANCE__, __BANK__) ((__INSTANCE__)->BTCR[(__BANK__)]\ + |= FMC_BCR1_MBKEN) + +/** + * @brief Disable the NORSRAM device access. + * @param __INSTANCE__ FMC_NORSRAM Instance + * @param __BANK__ FMC_NORSRAM Bank + * @retval None + */ +#define __FMC_NORSRAM_DISABLE(__INSTANCE__, __BANK__) ((__INSTANCE__)->BTCR[(__BANK__)]\ + &= ~FMC_BCR1_MBKEN) + +/** + * @} + */ +#endif /* FMC_Bank1 */ + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) +/** @defgroup FMC_LL_NAND_Macros FMC NAND Macros + * @brief macros to handle NAND device enable/disable + * @{ + */ + +/** + * @brief Enable the NAND device access. + * @param __INSTANCE__ FMC_NAND Instance + * @param __BANK__ FMC_NAND Bank + * @retval None + */ +#if defined(FMC_Bank2_3) +#if defined (FMC_PCR_PBKEN) +#define __FMC_NAND_ENABLE(__INSTANCE__) ((__INSTANCE__)->PCR |= FMC_PCR_PBKEN) +#else +#define __FMC_NAND_ENABLE(__INSTANCE__, __BANK__) (((__BANK__) == FMC_NAND_BANK2)? ((__INSTANCE__)->PCR2 |= FMC_PCR2_PBKEN): \ + ((__INSTANCE__)->PCR3 |= FMC_PCR3_PBKEN)) +#endif /* FMC_PCR_PBKEN */ +#else +#define __FMC_NAND_ENABLE(__INSTANCE__) ((__INSTANCE__)->PCR |= FMC_PCR_PBKEN) +#endif /* FMC_Bank2_3 */ + +/** + * @brief Disable the NAND device access. + * @param __INSTANCE__ FMC_NAND Instance + * @param __BANK__ FMC_NAND Bank + * @retval None + */ +#if defined(FMC_Bank2_3) +#if defined (FMC_PCR_PBKEN) +#define __FMC_NAND_DISABLE(__INSTANCE__, __BANK__) CLEAR_BIT((__INSTANCE__)->PCR, FMC_PCR_PBKEN) +#else +#define __FMC_NAND_DISABLE(__INSTANCE__, __BANK__) (((__BANK__) == FMC_NAND_BANK2)? CLEAR_BIT((__INSTANCE__)->PCR2, FMC_PCR2_PBKEN): \ + CLEAR_BIT((__INSTANCE__)->PCR3, FMC_PCR3_PBKEN)) +#endif /* FMC_PCR_PBKEN */ +#else +#define __FMC_NAND_DISABLE(__INSTANCE__, __BANK__) CLEAR_BIT((__INSTANCE__)->PCR, FMC_PCR_PBKEN) +#endif /* FMC_Bank2_3 */ + +/** + * @} + */ +#endif /* FMC_Bank3 || FMC_Bank2_3 */ + +#if defined(FMC_Bank4) +/** @defgroup FMC_LL_PCCARD_Macros FMC PCCARD Macros + * @brief macros to handle PCCARD read/write operations + * @{ + */ +/** + * @brief Enable the PCCARD device access. + * @param __INSTANCE__ FMC_PCCARD Instance + * @retval None + */ +#define __FMC_PCCARD_ENABLE(__INSTANCE__) ((__INSTANCE__)->PCR4 |= FMC_PCR4_PBKEN) + +/** + * @brief Disable the PCCARD device access. + * @param __INSTANCE__ FMC_PCCARD Instance + * @retval None + */ +#define __FMC_PCCARD_DISABLE(__INSTANCE__) ((__INSTANCE__)->PCR4 &= ~FMC_PCR4_PBKEN) +/** + * @} + */ + +#endif +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) +/** @defgroup FMC_LL_NAND_Interrupt FMC NAND Interrupt + * @brief macros to handle NAND interrupts + * @{ + */ + +/** + * @brief Enable the NAND device interrupt. + * @param __INSTANCE__ FMC_NAND instance + * @param __BANK__ FMC_NAND Bank + * @param __INTERRUPT__ FMC_NAND interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FMC_IT_LEVEL: Interrupt level. + * @arg FMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#if defined(FMC_Bank2_3) +#define __FMC_NAND_ENABLE_IT(__INSTANCE__, __BANK__, __INTERRUPT__) (((__BANK__) == FMC_NAND_BANK2)? ((__INSTANCE__)->SR2 |= (__INTERRUPT__)): \ + ((__INSTANCE__)->SR3 |= (__INTERRUPT__))) +#else +#define __FMC_NAND_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR |= (__INTERRUPT__)) +#endif /* FMC_Bank2_3 */ + +/** + * @brief Disable the NAND device interrupt. + * @param __INSTANCE__ FMC_NAND Instance + * @param __BANK__ FMC_NAND Bank + * @param __INTERRUPT__ FMC_NAND interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FMC_IT_LEVEL: Interrupt level. + * @arg FMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#if defined(FMC_Bank2_3) +#define __FMC_NAND_DISABLE_IT(__INSTANCE__, __BANK__, __INTERRUPT__) (((__BANK__) == FMC_NAND_BANK2)? ((__INSTANCE__)->SR2 &= ~(__INTERRUPT__)): \ + ((__INSTANCE__)->SR3 &= ~(__INTERRUPT__))) +#else +#define __FMC_NAND_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR &= ~(__INTERRUPT__)) +#endif /* FMC_Bank2_3 */ + +/** + * @brief Get flag status of the NAND device. + * @param __INSTANCE__ FMC_NAND Instance + * @param __BANK__ FMC_NAND Bank + * @param __FLAG__ FMC_NAND flag + * This parameter can be any combination of the following values: + * @arg FMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FMC_FLAG_FEMPT: FIFO empty flag. + * @retval The state of FLAG (SET or RESET). + */ +#if defined(FMC_Bank2_3) +#define __FMC_NAND_GET_FLAG(__INSTANCE__, __BANK__, __FLAG__) (((__BANK__) == FMC_NAND_BANK2)? (((__INSTANCE__)->SR2 &(__FLAG__)) == (__FLAG__)): \ + (((__INSTANCE__)->SR3 &(__FLAG__)) == (__FLAG__))) +#else +#define __FMC_NAND_GET_FLAG(__INSTANCE__, __BANK__, __FLAG__) (((__INSTANCE__)->SR &(__FLAG__)) == (__FLAG__)) +#endif /* FMC_Bank2_3 */ + +/** + * @brief Clear flag status of the NAND device. + * @param __INSTANCE__ FMC_NAND Instance + * @param __BANK__ FMC_NAND Bank + * @param __FLAG__ FMC_NAND flag + * This parameter can be any combination of the following values: + * @arg FMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FMC_FLAG_FEMPT: FIFO empty flag. + * @retval None + */ +#if defined(FMC_Bank2_3) +#define __FMC_NAND_CLEAR_FLAG(__INSTANCE__, __BANK__, __FLAG__) (((__BANK__) == FMC_NAND_BANK2)? ((__INSTANCE__)->SR2 &= ~(__FLAG__)): \ + ((__INSTANCE__)->SR3 &= ~(__FLAG__))) +#else +#define __FMC_NAND_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->SR &= ~(__FLAG__)) +#endif /* FMC_Bank2_3 */ + +/** + * @} + */ +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + +#if defined(FMC_Bank4) +/** @defgroup FMC_LL_PCCARD_Interrupt FMC PCCARD Interrupt + * @brief macros to handle PCCARD interrupts + * @{ + */ + +/** + * @brief Enable the PCCARD device interrupt. + * @param __INSTANCE__ FMC_PCCARD instance + * @param __INTERRUPT__ FMC_PCCARD interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FMC_IT_LEVEL: Interrupt level. + * @arg FMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FMC_PCCARD_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR4 |= (__INTERRUPT__)) + +/** + * @brief Disable the PCCARD device interrupt. + * @param __INSTANCE__ FMC_PCCARD instance + * @param __INTERRUPT__ FMC_PCCARD interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FMC_IT_LEVEL: Interrupt level. + * @arg FMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FMC_PCCARD_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR4 &= ~(__INTERRUPT__)) + +/** + * @brief Get flag status of the PCCARD device. + * @param __INSTANCE__ FMC_PCCARD instance + * @param __FLAG__ FMC_PCCARD flag + * This parameter can be any combination of the following values: + * @arg FMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FMC_FLAG_FEMPT: FIFO empty flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __FMC_PCCARD_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SR4 &(__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear flag status of the PCCARD device. + * @param __INSTANCE__ FMC_PCCARD instance + * @param __FLAG__ FMC_PCCARD flag + * This parameter can be any combination of the following values: + * @arg FMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FMC_FLAG_FEMPT: FIFO empty flag. + * @retval None + */ +#define __FMC_PCCARD_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->SR4 &= ~(__FLAG__)) + +/** + * @} + */ +#endif + +#if defined(FMC_Bank5_6) +/** @defgroup FMC_LL_SDRAM_Interrupt FMC SDRAM Interrupt + * @brief macros to handle SDRAM interrupts + * @{ + */ + +/** + * @brief Enable the SDRAM device interrupt. + * @param __INSTANCE__ FMC_SDRAM instance + * @param __INTERRUPT__ FMC_SDRAM interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_REFRESH_ERROR: Interrupt refresh error + * @retval None + */ +#define __FMC_SDRAM_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SDRTR |= (__INTERRUPT__)) + +/** + * @brief Disable the SDRAM device interrupt. + * @param __INSTANCE__ FMC_SDRAM instance + * @param __INTERRUPT__ FMC_SDRAM interrupt + * This parameter can be any combination of the following values: + * @arg FMC_IT_REFRESH_ERROR: Interrupt refresh error + * @retval None + */ +#define __FMC_SDRAM_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SDRTR &= ~(__INTERRUPT__)) + +/** + * @brief Get flag status of the SDRAM device. + * @param __INSTANCE__ FMC_SDRAM instance + * @param __FLAG__ FMC_SDRAM flag + * This parameter can be any combination of the following values: + * @arg FMC_SDRAM_FLAG_REFRESH_IT: Interrupt refresh error. + * @arg FMC_SDRAM_FLAG_BUSY: SDRAM busy flag. + * @arg FMC_SDRAM_FLAG_REFRESH_ERROR: Refresh error flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __FMC_SDRAM_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SDSR &(__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear flag status of the SDRAM device. + * @param __INSTANCE__ FMC_SDRAM instance + * @param __FLAG__ FMC_SDRAM flag + * This parameter can be any combination of the following values: + * @arg FMC_SDRAM_FLAG_REFRESH_ERROR + * @retval None + */ +#define __FMC_SDRAM_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->SDRTR |= (__FLAG__)) + +/** + * @} + */ +#endif /* FMC_Bank5_6 */ +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup FMC_LL_Private_Functions FMC LL Private Functions + * @{ + */ + +#if defined(FMC_Bank1) +/** @defgroup FMC_LL_NORSRAM NOR SRAM + * @{ + */ +/** @defgroup FMC_LL_NORSRAM_Private_Functions_Group1 NOR SRAM Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FMC_NORSRAM_Init(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_InitTypeDef *Init); +HAL_StatusTypeDef FMC_NORSRAM_Timing_Init(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_EXTENDED_TypeDef *Device, + FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, + uint32_t ExtendedMode); +HAL_StatusTypeDef FMC_NORSRAM_DeInit(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank); +/** + * @} + */ + +/** @defgroup FMC_LL_NORSRAM_Private_Functions_Group2 NOR SRAM Control functions + * @{ + */ +HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Enable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Disable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank); +/** + * @} + */ +/** + * @} + */ +#endif /* FMC_Bank1 */ + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) +/** @defgroup FMC_LL_NAND NAND + * @{ + */ +/** @defgroup FMC_LL_NAND_Private_Functions_Group1 NAND Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FMC_NAND_Init(FMC_NAND_TypeDef *Device, FMC_NAND_InitTypeDef *Init); +HAL_StatusTypeDef FMC_NAND_CommonSpace_Timing_Init(FMC_NAND_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FMC_NAND_AttributeSpace_Timing_Init(FMC_NAND_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FMC_NAND_DeInit(FMC_NAND_TypeDef *Device, uint32_t Bank); +/** + * @} + */ + +/** @defgroup FMC_LL_NAND_Private_Functions_Group2 NAND Control functions + * @{ + */ +HAL_StatusTypeDef FMC_NAND_ECC_Enable(FMC_NAND_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FMC_NAND_ECC_Disable(FMC_NAND_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FMC_NAND_GetECC(FMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, + uint32_t Timeout); +/** + * @} + */ +/** + * @} + */ +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + +#if defined(FMC_Bank4) +/** @defgroup FMC_LL_PCCARD PCCARD + * @{ + */ +/** @defgroup FMC_LL_PCCARD_Private_Functions_Group1 PCCARD Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FMC_PCCARD_Init(FMC_PCCARD_TypeDef *Device, FMC_PCCARD_InitTypeDef *Init); +HAL_StatusTypeDef FMC_PCCARD_CommonSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FMC_PCCARD_AttributeSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FMC_PCCARD_IOSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FMC_PCCARD_DeInit(FMC_PCCARD_TypeDef *Device); +/** + * @} + */ +/** + * @} + */ +#endif /* FMC_Bank4 */ + +#if defined(FMC_Bank5_6) +/** @defgroup FMC_LL_SDRAM SDRAM + * @{ + */ +/** @defgroup FMC_LL_SDRAM_Private_Functions_Group1 SDRAM Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDef *Init); +HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, + FMC_SDRAM_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FMC_SDRAM_DeInit(FMC_SDRAM_TypeDef *Device, uint32_t Bank); +/** + * @} + */ + +/** @defgroup FMC_LL_SDRAM_Private_Functions_Group2 SDRAM Control functions + * @{ + */ +HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Enable(FMC_SDRAM_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Disable(FMC_SDRAM_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FMC_SDRAM_SendCommand(FMC_SDRAM_TypeDef *Device, + FMC_SDRAM_CommandTypeDef *Command, uint32_t Timeout); +HAL_StatusTypeDef FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_TypeDef *Device, uint32_t RefreshRate); +HAL_StatusTypeDef FMC_SDRAM_SetAutoRefreshNumber(FMC_SDRAM_TypeDef *Device, + uint32_t AutoRefreshNumber); +uint32_t FMC_SDRAM_GetModeStatus(FMC_SDRAM_TypeDef *Device, uint32_t Bank); +/** + * @} + */ +/** + * @} + */ +#endif /* FMC_Bank5_6 */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_FMC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h new file mode 100644 index 0000000..dcc0016 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fmpi2c.h @@ -0,0 +1,2234 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fmpi2c.h + * @author MCD Application Team + * @brief Header file of FMPI2C 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 STM32F4xx_LL_FMPI2C_H +#define STM32F4xx_LL_FMPI2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (FMPI2C1) + +/** @defgroup FMPI2C_LL FMPI2C + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FMPI2C_LL_Private_Constants FMPI2C Private Constants + * @{ + */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup FMPI2C_LL_Private_Macros FMPI2C Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup FMPI2C_LL_ES_INIT FMPI2C Exported Init structure + * @{ + */ +typedef struct +{ + uint32_t PeripheralMode; /*!< Specifies the peripheral mode. + This parameter can be a value of @ref FMPI2C_LL_EC_PERIPHERAL_MODE. + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_SetMode(). */ + + uint32_t Timing; /*!< Specifies the SDA setup, hold time and the SCL high, low period values. + This parameter must be set by referring to the STM32CubeMX Tool and + the helper macro @ref __LL_FMPI2C_CONVERT_TIMINGS(). + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_SetTiming(). */ + + uint32_t AnalogFilter; /*!< Enables or disables analog noise filter. + This parameter can be a value of @ref FMPI2C_LL_EC_ANALOGFILTER_SELECTION. + + This feature can be modified afterwards using unitary functions + @ref LL_FMPI2C_EnableAnalogFilter() or LL_FMPI2C_DisableAnalogFilter(). */ + + uint32_t DigitalFilter; /*!< Configures the digital noise filter. + This parameter can be a number between Min_Data = 0x00 and Max_Data = 0x0F. + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_SetDigitalFilter(). */ + + uint32_t OwnAddress1; /*!< Specifies the device own address 1. + This parameter must be a value between Min_Data = 0x00 and Max_Data = 0x3FF. + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_SetOwnAddress1(). */ + + uint32_t TypeAcknowledge; /*!< Specifies the ACKnowledge or Non ACKnowledge condition after the address receive + match code or next received byte. + This parameter can be a value of @ref FMPI2C_LL_EC_I2C_ACKNOWLEDGE. + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_AcknowledgeNextData(). */ + + uint32_t OwnAddrSize; /*!< Specifies the device own address 1 size (7-bit or 10-bit). + This parameter can be a value of @ref FMPI2C_LL_EC_OWNADDRESS1. + + This feature can be modified afterwards using unitary function + @ref LL_FMPI2C_SetOwnAddress1(). */ +} LL_FMPI2C_InitTypeDef; +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup FMPI2C_LL_Exported_Constants FMPI2C Exported Constants + * @{ + */ + +/** @defgroup FMPI2C_LL_EC_CLEAR_FLAG Clear Flags Defines + * @brief Flags defines which can be used with LL_FMPI2C_WriteReg function + * @{ + */ +#define LL_FMPI2C_ICR_ADDRCF FMPI2C_ICR_ADDRCF /*!< Address Matched flag */ +#define LL_FMPI2C_ICR_NACKCF FMPI2C_ICR_NACKCF /*!< Not Acknowledge flag */ +#define LL_FMPI2C_ICR_STOPCF FMPI2C_ICR_STOPCF /*!< Stop detection flag */ +#define LL_FMPI2C_ICR_BERRCF FMPI2C_ICR_BERRCF /*!< Bus error flag */ +#define LL_FMPI2C_ICR_ARLOCF FMPI2C_ICR_ARLOCF /*!< Arbitration Lost flag */ +#define LL_FMPI2C_ICR_OVRCF FMPI2C_ICR_OVRCF /*!< Overrun/Underrun flag */ +#define LL_FMPI2C_ICR_PECCF FMPI2C_ICR_PECCF /*!< PEC error flag */ +#define LL_FMPI2C_ICR_TIMOUTCF FMPI2C_ICR_TIMOUTCF /*!< Timeout detection flag */ +#define LL_FMPI2C_ICR_ALERTCF FMPI2C_ICR_ALERTCF /*!< Alert flag */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_FMPI2C_ReadReg function + * @{ + */ +#define LL_FMPI2C_ISR_TXE FMPI2C_ISR_TXE /*!< Transmit data register empty */ +#define LL_FMPI2C_ISR_TXIS FMPI2C_ISR_TXIS /*!< Transmit interrupt status */ +#define LL_FMPI2C_ISR_RXNE FMPI2C_ISR_RXNE /*!< Receive data register not empty */ +#define LL_FMPI2C_ISR_ADDR FMPI2C_ISR_ADDR /*!< Address matched (slave mode) */ +#define LL_FMPI2C_ISR_NACKF FMPI2C_ISR_NACKF /*!< Not Acknowledge received flag */ +#define LL_FMPI2C_ISR_STOPF FMPI2C_ISR_STOPF /*!< Stop detection flag */ +#define LL_FMPI2C_ISR_TC FMPI2C_ISR_TC /*!< Transfer Complete (master mode) */ +#define LL_FMPI2C_ISR_TCR FMPI2C_ISR_TCR /*!< Transfer Complete Reload */ +#define LL_FMPI2C_ISR_BERR FMPI2C_ISR_BERR /*!< Bus error */ +#define LL_FMPI2C_ISR_ARLO FMPI2C_ISR_ARLO /*!< Arbitration lost */ +#define LL_FMPI2C_ISR_OVR FMPI2C_ISR_OVR /*!< Overrun/Underrun (slave mode) */ +#define LL_FMPI2C_ISR_PECERR FMPI2C_ISR_PECERR /*!< PEC Error in reception (SMBus mode) */ +#define LL_FMPI2C_ISR_TIMEOUT FMPI2C_ISR_TIMEOUT /*!< Timeout detection flag (SMBus mode) */ +#define LL_FMPI2C_ISR_ALERT FMPI2C_ISR_ALERT /*!< SMBus alert (SMBus mode) */ +#define LL_FMPI2C_ISR_BUSY FMPI2C_ISR_BUSY /*!< Bus busy */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_FMPI2C_ReadReg and LL_FMPI2C_WriteReg functions + * @{ + */ +#define LL_FMPI2C_CR1_TXIE FMPI2C_CR1_TXIE /*!< TX Interrupt enable */ +#define LL_FMPI2C_CR1_RXIE FMPI2C_CR1_RXIE /*!< RX Interrupt enable */ +#define LL_FMPI2C_CR1_ADDRIE FMPI2C_CR1_ADDRIE /*!< Address match Interrupt enable (slave only) */ +#define LL_FMPI2C_CR1_NACKIE FMPI2C_CR1_NACKIE /*!< Not acknowledge received Interrupt enable */ +#define LL_FMPI2C_CR1_STOPIE FMPI2C_CR1_STOPIE /*!< STOP detection Interrupt enable */ +#define LL_FMPI2C_CR1_TCIE FMPI2C_CR1_TCIE /*!< Transfer Complete interrupt enable */ +#define LL_FMPI2C_CR1_ERRIE FMPI2C_CR1_ERRIE /*!< Error interrupts enable */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_PERIPHERAL_MODE Peripheral Mode + * @{ + */ +#define LL_FMPI2C_MODE_I2C 0x00000000U /*!< FMPI2C Master or Slave mode */ +#define LL_FMPI2C_MODE_SMBUS_HOST FMPI2C_CR1_SMBHEN /*!< SMBus Host address acknowledge */ +#define LL_FMPI2C_MODE_SMBUS_DEVICE 0x00000000U /*!< SMBus Device default mode + (Default address not acknowledge) */ +#define LL_FMPI2C_MODE_SMBUS_DEVICE_ARP FMPI2C_CR1_SMBDEN /*!< SMBus Device Default address acknowledge */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_ANALOGFILTER_SELECTION Analog Filter Selection + * @{ + */ +#define LL_FMPI2C_ANALOGFILTER_ENABLE 0x00000000U /*!< Analog filter is enabled. */ +#define LL_FMPI2C_ANALOGFILTER_DISABLE FMPI2C_CR1_ANFOFF /*!< Analog filter is disabled. */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_ADDRESSING_MODE Master Addressing Mode + * @{ + */ +#define LL_FMPI2C_ADDRESSING_MODE_7BIT 0x00000000U /*!< Master operates in 7-bit addressing mode. */ +#define LL_FMPI2C_ADDRESSING_MODE_10BIT FMPI2C_CR2_ADD10 /*!< Master operates in 10-bit addressing mode.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_OWNADDRESS1 Own Address 1 Length + * @{ + */ +#define LL_FMPI2C_OWNADDRESS1_7BIT 0x00000000U /*!< Own address 1 is a 7-bit address. */ +#define LL_FMPI2C_OWNADDRESS1_10BIT FMPI2C_OAR1_OA1MODE /*!< Own address 1 is a 10-bit address.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_OWNADDRESS2 Own Address 2 Masks + * @{ + */ +#define LL_FMPI2C_OWNADDRESS2_NOMASK FMPI2C_OAR2_OA2NOMASK /*!< Own Address2 No mask. */ +#define LL_FMPI2C_OWNADDRESS2_MASK01 FMPI2C_OAR2_OA2MASK01 /*!< Only Address2 bits[7:2] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK02 FMPI2C_OAR2_OA2MASK02 /*!< Only Address2 bits[7:3] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK03 FMPI2C_OAR2_OA2MASK03 /*!< Only Address2 bits[7:4] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK04 FMPI2C_OAR2_OA2MASK04 /*!< Only Address2 bits[7:5] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK05 FMPI2C_OAR2_OA2MASK05 /*!< Only Address2 bits[7:6] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK06 FMPI2C_OAR2_OA2MASK06 /*!< Only Address2 bits[7] are compared. */ +#define LL_FMPI2C_OWNADDRESS2_MASK07 FMPI2C_OAR2_OA2MASK07 /*!< No comparison is done. + All Address2 are acknowledged. */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_I2C_ACKNOWLEDGE Acknowledge Generation + * @{ + */ +#define LL_FMPI2C_ACK 0x00000000U /*!< ACK is sent after current received byte. */ +#define LL_FMPI2C_NACK FMPI2C_CR2_NACK /*!< NACK is sent after current received byte.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_ADDRSLAVE Slave Address Length + * @{ + */ +#define LL_FMPI2C_ADDRSLAVE_7BIT 0x00000000U /*!< Slave Address in 7-bit. */ +#define LL_FMPI2C_ADDRSLAVE_10BIT FMPI2C_CR2_ADD10 /*!< Slave Address in 10-bit.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_REQUEST Transfer Request Direction + * @{ + */ +#define LL_FMPI2C_REQUEST_WRITE 0x00000000U /*!< Master request a write transfer. */ +#define LL_FMPI2C_REQUEST_READ FMPI2C_CR2_RD_WRN /*!< Master request a read transfer. */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_MODE Transfer End Mode + * @{ + */ +#define LL_FMPI2C_MODE_RELOAD FMPI2C_CR2_RELOAD /*!< Enable FMPI2C Reload mode. */ +#define LL_FMPI2C_MODE_AUTOEND FMPI2C_CR2_AUTOEND /*!< Enable FMPI2C Automatic end mode + with no HW PEC comparison. */ +#define LL_FMPI2C_MODE_SOFTEND 0x00000000U /*!< Enable FMPI2C Software end mode + with no HW PEC comparison. */ +#define LL_FMPI2C_MODE_SMBUS_RELOAD LL_FMPI2C_MODE_RELOAD /*!< Enable FMPSMBUS Automatic end mode + with HW PEC comparison. */ +#define LL_FMPI2C_MODE_SMBUS_AUTOEND_NO_PEC LL_FMPI2C_MODE_AUTOEND /*!< Enable FMPSMBUS Automatic end mode + with HW PEC comparison. */ +#define LL_FMPI2C_MODE_SMBUS_SOFTEND_NO_PEC LL_FMPI2C_MODE_SOFTEND /*!< Enable FMPSMBUS Software end mode + with HW PEC comparison. */ +#define LL_FMPI2C_MODE_SMBUS_AUTOEND_WITH_PEC (uint32_t)(LL_FMPI2C_MODE_AUTOEND | FMPI2C_CR2_PECBYTE) +/*!< Enable FMPSMBUS Automatic end mode with HW PEC comparison. */ +#define LL_FMPI2C_MODE_SMBUS_SOFTEND_WITH_PEC (uint32_t)(LL_FMPI2C_MODE_SOFTEND | FMPI2C_CR2_PECBYTE) +/*!< Enable FMPSMBUS Software end mode with HW PEC comparison. */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_GENERATE Start And Stop Generation + * @{ + */ +#define LL_FMPI2C_GENERATE_NOSTARTSTOP 0x00000000U +/*!< Don't Generate Stop and Start condition. */ +#define LL_FMPI2C_GENERATE_STOP (uint32_t)(0x80000000U | FMPI2C_CR2_STOP) +/*!< Generate Stop condition (Size should be set to 0). */ +#define LL_FMPI2C_GENERATE_START_READ (uint32_t)(0x80000000U | FMPI2C_CR2_START | FMPI2C_CR2_RD_WRN) +/*!< Generate Start for read request. */ +#define LL_FMPI2C_GENERATE_START_WRITE (uint32_t)(0x80000000U | FMPI2C_CR2_START) +/*!< Generate Start for write request. */ +#define LL_FMPI2C_GENERATE_RESTART_7BIT_READ (uint32_t)(0x80000000U | FMPI2C_CR2_START | FMPI2C_CR2_RD_WRN) +/*!< Generate Restart for read request, slave 7Bit address. */ +#define LL_FMPI2C_GENERATE_RESTART_7BIT_WRITE (uint32_t)(0x80000000U | FMPI2C_CR2_START) +/*!< Generate Restart for write request, slave 7Bit address. */ +#define LL_FMPI2C_GENERATE_RESTART_10BIT_READ (uint32_t)(0x80000000U | FMPI2C_CR2_START | \ + FMPI2C_CR2_RD_WRN | FMPI2C_CR2_HEAD10R) +/*!< Generate Restart for read request, slave 10Bit address. */ +#define LL_FMPI2C_GENERATE_RESTART_10BIT_WRITE (uint32_t)(0x80000000U | FMPI2C_CR2_START) +/*!< Generate Restart for write request, slave 10Bit address.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_DIRECTION Read Write Direction + * @{ + */ +#define LL_FMPI2C_DIRECTION_WRITE 0x00000000U /*!< Write transfer request by master, + slave enters receiver mode. */ +#define LL_FMPI2C_DIRECTION_READ FMPI2C_ISR_DIR /*!< Read transfer request by master, + slave enters transmitter mode.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_DMA_REG_DATA DMA Register Data + * @{ + */ +#define LL_FMPI2C_DMA_REG_DATA_TRANSMIT 0x00000000U /*!< Get address of data register used for + transmission */ +#define LL_FMPI2C_DMA_REG_DATA_RECEIVE 0x00000001U /*!< Get address of data register used for + reception */ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_SMBUS_TIMEOUTA_MODE SMBus TimeoutA Mode SCL SDA Timeout + * @{ + */ +#define LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SCL_LOW 0x00000000U /*!< TimeoutA is used to detect + SCL low level timeout. */ +#define LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH FMPI2C_TIMEOUTR_TIDLE /*!< TimeoutA is used to detect + both SCL and SDA high level timeout.*/ +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EC_SMBUS_TIMEOUT_SELECTION SMBus Timeout Selection + * @{ + */ +#define LL_FMPI2C_FMPSMBUS_TIMEOUTA FMPI2C_TIMEOUTR_TIMOUTEN /*!< TimeoutA enable bit */ +#define LL_FMPI2C_FMPSMBUS_TIMEOUTB FMPI2C_TIMEOUTR_TEXTEN /*!< TimeoutB (extended clock) + enable bit */ +#define LL_FMPI2C_FMPSMBUS_ALL_TIMEOUT (uint32_t)(FMPI2C_TIMEOUTR_TIMOUTEN | \ + FMPI2C_TIMEOUTR_TEXTEN) /*!< TimeoutA and TimeoutB +(extended clock) enable bits */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup FMPI2C_LL_Exported_Macros FMPI2C Exported Macros + * @{ + */ + +/** @defgroup FMPI2C_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in FMPI2C register + * @param __INSTANCE__ FMPI2C Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_FMPI2C_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in FMPI2C register + * @param __INSTANCE__ FMPI2C Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_FMPI2C_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EM_CONVERT_TIMINGS Convert SDA SCL timings + * @{ + */ +/** + * @brief Configure the SDA setup, hold time and the SCL high, low period. + * @param __PRESCALER__ This parameter must be a value between Min_Data=0 and Max_Data=0xF. + * @param __SETUP_TIME__ This parameter must be a value between Min_Data=0 and Max_Data=0xF. + (tscldel = (SCLDEL+1)xtpresc) + * @param __HOLD_TIME__ This parameter must be a value between Min_Data=0 and Max_Data=0xF. + (tsdadel = SDADELxtpresc) + * @param __SCLH_PERIOD__ This parameter must be a value between Min_Data=0 and Max_Data=0xFF. + (tsclh = (SCLH+1)xtpresc) + * @param __SCLL_PERIOD__ This parameter must be a value between Min_Data=0 and Max_Data=0xFF. + (tscll = (SCLL+1)xtpresc) + * @retval Value between Min_Data=0 and Max_Data=0xFFFFFFFF + */ +#define __LL_FMPI2C_CONVERT_TIMINGS(__PRESCALER__, __SETUP_TIME__, __HOLD_TIME__, __SCLH_PERIOD__, __SCLL_PERIOD__) \ + ((((uint32_t)(__PRESCALER__) << FMPI2C_TIMINGR_PRESC_Pos) & FMPI2C_TIMINGR_PRESC) | \ + (((uint32_t)(__SETUP_TIME__) << FMPI2C_TIMINGR_SCLDEL_Pos) & FMPI2C_TIMINGR_SCLDEL) | \ + (((uint32_t)(__HOLD_TIME__) << FMPI2C_TIMINGR_SDADEL_Pos) & FMPI2C_TIMINGR_SDADEL) | \ + (((uint32_t)(__SCLH_PERIOD__) << FMPI2C_TIMINGR_SCLH_Pos) & FMPI2C_TIMINGR_SCLH) | \ + (((uint32_t)(__SCLL_PERIOD__) << FMPI2C_TIMINGR_SCLL_Pos) & FMPI2C_TIMINGR_SCLL)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup FMPI2C_LL_Exported_Functions FMPI2C Exported Functions + * @{ + */ + +/** @defgroup FMPI2C_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable FMPI2C peripheral (PE = 1). + * @rmtoll CR1 PE LL_FMPI2C_Enable + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_Enable(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PE); +} + +/** + * @brief Disable FMPI2C peripheral (PE = 0). + * @note When PE = 0, the FMPI2C SCL and SDA lines are released. + * Internal state machines and status bits are put back to their reset value. + * When cleared, PE must be kept low for at least 3 APB clock cycles. + * @rmtoll CR1 PE LL_FMPI2C_Disable + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_Disable(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PE); +} + +/** + * @brief Check if the FMPI2C peripheral is enabled or disabled. + * @rmtoll CR1 PE LL_FMPI2C_IsEnabled + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabled(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PE) == (FMPI2C_CR1_PE)) ? 1UL : 0UL); +} + +/** + * @brief Configure Noise Filters (Analog and Digital). + * @note If the analog filter is also enabled, the digital filter is added to analog filter. + * The filters can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_FMPI2C_ConfigFilters\n + * CR1 DNF LL_FMPI2C_ConfigFilters + * @param FMPI2Cx FMPI2C Instance. + * @param AnalogFilter This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_ANALOGFILTER_ENABLE + * @arg @ref LL_FMPI2C_ANALOGFILTER_DISABLE + * @param DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled) + and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*tfmpi2cclk). + * This parameter is used to configure the digital noise filter on SDA and SCL input. + * The digital filter will filter spikes with a length of up to DNF[3:0]*tfmpi2cclk. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ConfigFilters(FMPI2C_TypeDef *FMPI2Cx, uint32_t AnalogFilter, uint32_t DigitalFilter) +{ + MODIFY_REG(FMPI2Cx->CR1, FMPI2C_CR1_ANFOFF | FMPI2C_CR1_DNF, AnalogFilter | (DigitalFilter << FMPI2C_CR1_DNF_Pos)); +} + +/** + * @brief Configure Digital Noise Filter. + * @note If the analog filter is also enabled, the digital filter is added to analog filter. + * This filter can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 DNF LL_FMPI2C_SetDigitalFilter + * @param FMPI2Cx FMPI2C Instance. + * @param DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled) + and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*tfmpi2cclk). + * This parameter is used to configure the digital noise filter on SDA and SCL input. + * The digital filter will filter spikes with a length of up to DNF[3:0]*tfmpi2cclk. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetDigitalFilter(FMPI2C_TypeDef *FMPI2Cx, uint32_t DigitalFilter) +{ + MODIFY_REG(FMPI2Cx->CR1, FMPI2C_CR1_DNF, DigitalFilter << FMPI2C_CR1_DNF_Pos); +} + +/** + * @brief Get the current Digital Noise Filter configuration. + * @rmtoll CR1 DNF LL_FMPI2C_GetDigitalFilter + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetDigitalFilter(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_DNF) >> FMPI2C_CR1_DNF_Pos); +} + +/** + * @brief Enable Analog Noise Filter. + * @note This filter can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_FMPI2C_EnableAnalogFilter + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableAnalogFilter(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ANFOFF); +} + +/** + * @brief Disable Analog Noise Filter. + * @note This filter can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 ANFOFF LL_FMPI2C_DisableAnalogFilter + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableAnalogFilter(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ANFOFF); +} + +/** + * @brief Check if Analog Noise Filter is enabled or disabled. + * @rmtoll CR1 ANFOFF LL_FMPI2C_IsEnabledAnalogFilter + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledAnalogFilter(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ANFOFF) != (FMPI2C_CR1_ANFOFF)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA transmission requests. + * @rmtoll CR1 TXDMAEN LL_FMPI2C_EnableDMAReq_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableDMAReq_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXDMAEN); +} + +/** + * @brief Disable DMA transmission requests. + * @rmtoll CR1 TXDMAEN LL_FMPI2C_DisableDMAReq_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableDMAReq_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXDMAEN); +} + +/** + * @brief Check if DMA transmission requests are enabled or disabled. + * @rmtoll CR1 TXDMAEN LL_FMPI2C_IsEnabledDMAReq_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledDMAReq_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXDMAEN) == (FMPI2C_CR1_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA reception requests. + * @rmtoll CR1 RXDMAEN LL_FMPI2C_EnableDMAReq_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableDMAReq_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXDMAEN); +} + +/** + * @brief Disable DMA reception requests. + * @rmtoll CR1 RXDMAEN LL_FMPI2C_DisableDMAReq_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableDMAReq_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXDMAEN); +} + +/** + * @brief Check if DMA reception requests are enabled or disabled. + * @rmtoll CR1 RXDMAEN LL_FMPI2C_IsEnabledDMAReq_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledDMAReq_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXDMAEN) == (FMPI2C_CR1_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll TXDR TXDATA LL_FMPI2C_DMA_GetRegAddr\n + * RXDR RXDATA LL_FMPI2C_DMA_GetRegAddr + * @param FMPI2Cx FMPI2C Instance + * @param Direction This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_DMA_REG_DATA_TRANSMIT + * @arg @ref LL_FMPI2C_DMA_REG_DATA_RECEIVE + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_FMPI2C_DMA_GetRegAddr(FMPI2C_TypeDef *FMPI2Cx, uint32_t Direction) +{ + uint32_t data_reg_addr; + + if (Direction == LL_FMPI2C_DMA_REG_DATA_TRANSMIT) + { + /* return address of TXDR register */ + data_reg_addr = (uint32_t) &(FMPI2Cx->TXDR); + } + else + { + /* return address of RXDR register */ + data_reg_addr = (uint32_t) &(FMPI2Cx->RXDR); + } + + return data_reg_addr; +} + +/** + * @brief Enable Clock stretching. + * @note This bit can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 NOSTRETCH LL_FMPI2C_EnableClockStretching + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableClockStretching(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NOSTRETCH); +} + +/** + * @brief Disable Clock stretching. + * @note This bit can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll CR1 NOSTRETCH LL_FMPI2C_DisableClockStretching + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableClockStretching(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NOSTRETCH); +} + +/** + * @brief Check if Clock stretching is enabled or disabled. + * @rmtoll CR1 NOSTRETCH LL_FMPI2C_IsEnabledClockStretching + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledClockStretching(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NOSTRETCH) != (FMPI2C_CR1_NOSTRETCH)) ? 1UL : 0UL); +} + +/** + * @brief Enable hardware byte control in slave mode. + * @rmtoll CR1 SBC LL_FMPI2C_EnableSlaveByteControl + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableSlaveByteControl(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_SBC); +} + +/** + * @brief Disable hardware byte control in slave mode. + * @rmtoll CR1 SBC LL_FMPI2C_DisableSlaveByteControl + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableSlaveByteControl(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_SBC); +} + +/** + * @brief Check if hardware byte control in slave mode is enabled or disabled. + * @rmtoll CR1 SBC LL_FMPI2C_IsEnabledSlaveByteControl + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledSlaveByteControl(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_SBC) == (FMPI2C_CR1_SBC)) ? 1UL : 0UL); +} + +/** + * @brief Enable General Call. + * @note When enabled the Address 0x00 is ACKed. + * @rmtoll CR1 GCEN LL_FMPI2C_EnableGeneralCall + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableGeneralCall(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_GCEN); +} + +/** + * @brief Disable General Call. + * @note When disabled the Address 0x00 is NACKed. + * @rmtoll CR1 GCEN LL_FMPI2C_DisableGeneralCall + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableGeneralCall(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_GCEN); +} + +/** + * @brief Check if General Call is enabled or disabled. + * @rmtoll CR1 GCEN LL_FMPI2C_IsEnabledGeneralCall + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledGeneralCall(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_GCEN) == (FMPI2C_CR1_GCEN)) ? 1UL : 0UL); +} + +/** + * @brief Configure the Master to operate in 7-bit or 10-bit addressing mode. + * @note Changing this bit is not allowed, when the START bit is set. + * @rmtoll CR2 ADD10 LL_FMPI2C_SetMasterAddressingMode + * @param FMPI2Cx FMPI2C Instance. + * @param AddressingMode This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_ADDRESSING_MODE_7BIT + * @arg @ref LL_FMPI2C_ADDRESSING_MODE_10BIT + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetMasterAddressingMode(FMPI2C_TypeDef *FMPI2Cx, uint32_t AddressingMode) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_ADD10, AddressingMode); +} + +/** + * @brief Get the Master addressing mode. + * @rmtoll CR2 ADD10 LL_FMPI2C_GetMasterAddressingMode + * @param FMPI2Cx FMPI2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_FMPI2C_ADDRESSING_MODE_7BIT + * @arg @ref LL_FMPI2C_ADDRESSING_MODE_10BIT + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetMasterAddressingMode(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_ADD10)); +} + +/** + * @brief Set the Own Address1. + * @rmtoll OAR1 OA1 LL_FMPI2C_SetOwnAddress1\n + * OAR1 OA1MODE LL_FMPI2C_SetOwnAddress1 + * @param FMPI2Cx FMPI2C Instance. + * @param OwnAddress1 This parameter must be a value between Min_Data=0 and Max_Data=0x3FF. + * @param OwnAddrSize This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_OWNADDRESS1_7BIT + * @arg @ref LL_FMPI2C_OWNADDRESS1_10BIT + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetOwnAddress1(FMPI2C_TypeDef *FMPI2Cx, uint32_t OwnAddress1, uint32_t OwnAddrSize) +{ + MODIFY_REG(FMPI2Cx->OAR1, FMPI2C_OAR1_OA1 | FMPI2C_OAR1_OA1MODE, OwnAddress1 | OwnAddrSize); +} + +/** + * @brief Enable acknowledge on Own Address1 match address. + * @rmtoll OAR1 OA1EN LL_FMPI2C_EnableOwnAddress1 + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableOwnAddress1(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->OAR1, FMPI2C_OAR1_OA1EN); +} + +/** + * @brief Disable acknowledge on Own Address1 match address. + * @rmtoll OAR1 OA1EN LL_FMPI2C_DisableOwnAddress1 + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableOwnAddress1(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->OAR1, FMPI2C_OAR1_OA1EN); +} + +/** + * @brief Check if Own Address1 acknowledge is enabled or disabled. + * @rmtoll OAR1 OA1EN LL_FMPI2C_IsEnabledOwnAddress1 + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledOwnAddress1(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->OAR1, FMPI2C_OAR1_OA1EN) == (FMPI2C_OAR1_OA1EN)) ? 1UL : 0UL); +} + +/** + * @brief Set the 7bits Own Address2. + * @note This action has no effect if own address2 is enabled. + * @rmtoll OAR2 OA2 LL_FMPI2C_SetOwnAddress2\n + * OAR2 OA2MSK LL_FMPI2C_SetOwnAddress2 + * @param FMPI2Cx FMPI2C Instance. + * @param OwnAddress2 Value between Min_Data=0 and Max_Data=0x7F. + * @param OwnAddrMask This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_OWNADDRESS2_NOMASK + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK01 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK02 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK03 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK04 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK05 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK06 + * @arg @ref LL_FMPI2C_OWNADDRESS2_MASK07 + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetOwnAddress2(FMPI2C_TypeDef *FMPI2Cx, uint32_t OwnAddress2, uint32_t OwnAddrMask) +{ + MODIFY_REG(FMPI2Cx->OAR2, FMPI2C_OAR2_OA2 | FMPI2C_OAR2_OA2MSK, OwnAddress2 | OwnAddrMask); +} + +/** + * @brief Enable acknowledge on Own Address2 match address. + * @rmtoll OAR2 OA2EN LL_FMPI2C_EnableOwnAddress2 + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableOwnAddress2(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->OAR2, FMPI2C_OAR2_OA2EN); +} + +/** + * @brief Disable acknowledge on Own Address2 match address. + * @rmtoll OAR2 OA2EN LL_FMPI2C_DisableOwnAddress2 + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableOwnAddress2(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->OAR2, FMPI2C_OAR2_OA2EN); +} + +/** + * @brief Check if Own Address1 acknowledge is enabled or disabled. + * @rmtoll OAR2 OA2EN LL_FMPI2C_IsEnabledOwnAddress2 + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledOwnAddress2(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->OAR2, FMPI2C_OAR2_OA2EN) == (FMPI2C_OAR2_OA2EN)) ? 1UL : 0UL); +} + +/** + * @brief Configure the SDA setup, hold time and the SCL high, low period. + * @note This bit can only be programmed when the FMPI2C is disabled (PE = 0). + * @rmtoll TIMINGR TIMINGR LL_FMPI2C_SetTiming + * @param FMPI2Cx FMPI2C Instance. + * @param Timing This parameter must be a value between Min_Data=0 and Max_Data=0xFFFFFFFF. + * @note This parameter is computed with the STM32CubeMX Tool. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetTiming(FMPI2C_TypeDef *FMPI2Cx, uint32_t Timing) +{ + WRITE_REG(FMPI2Cx->TIMINGR, Timing); +} + +/** + * @brief Get the Timing Prescaler setting. + * @rmtoll TIMINGR PRESC LL_FMPI2C_GetTimingPrescaler + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetTimingPrescaler(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMINGR, FMPI2C_TIMINGR_PRESC) >> FMPI2C_TIMINGR_PRESC_Pos); +} + +/** + * @brief Get the SCL low period setting. + * @rmtoll TIMINGR SCLL LL_FMPI2C_GetClockLowPeriod + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetClockLowPeriod(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMINGR, FMPI2C_TIMINGR_SCLL) >> FMPI2C_TIMINGR_SCLL_Pos); +} + +/** + * @brief Get the SCL high period setting. + * @rmtoll TIMINGR SCLH LL_FMPI2C_GetClockHighPeriod + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetClockHighPeriod(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMINGR, FMPI2C_TIMINGR_SCLH) >> FMPI2C_TIMINGR_SCLH_Pos); +} + +/** + * @brief Get the SDA hold time. + * @rmtoll TIMINGR SDADEL LL_FMPI2C_GetDataHoldTime + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetDataHoldTime(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMINGR, FMPI2C_TIMINGR_SDADEL) >> FMPI2C_TIMINGR_SDADEL_Pos); +} + +/** + * @brief Get the SDA setup time. + * @rmtoll TIMINGR SCLDEL LL_FMPI2C_GetDataSetupTime + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetDataSetupTime(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMINGR, FMPI2C_TIMINGR_SCLDEL) >> FMPI2C_TIMINGR_SCLDEL_Pos); +} + +/** + * @brief Configure peripheral mode. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 SMBHEN LL_FMPI2C_SetMode\n + * CR1 SMBDEN LL_FMPI2C_SetMode + * @param FMPI2Cx FMPI2C Instance. + * @param PeripheralMode This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_MODE_I2C + * @arg @ref LL_FMPI2C_MODE_SMBUS_HOST + * @arg @ref LL_FMPI2C_MODE_SMBUS_DEVICE + * @arg @ref LL_FMPI2C_MODE_SMBUS_DEVICE_ARP + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetMode(FMPI2C_TypeDef *FMPI2Cx, uint32_t PeripheralMode) +{ + MODIFY_REG(FMPI2Cx->CR1, FMPI2C_CR1_SMBHEN | FMPI2C_CR1_SMBDEN, PeripheralMode); +} + +/** + * @brief Get peripheral mode. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 SMBHEN LL_FMPI2C_GetMode\n + * CR1 SMBDEN LL_FMPI2C_GetMode + * @param FMPI2Cx FMPI2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_FMPI2C_MODE_I2C + * @arg @ref LL_FMPI2C_MODE_SMBUS_HOST + * @arg @ref LL_FMPI2C_MODE_SMBUS_DEVICE + * @arg @ref LL_FMPI2C_MODE_SMBUS_DEVICE_ARP + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetMode(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_SMBHEN | FMPI2C_CR1_SMBDEN)); +} + +/** + * @brief Enable SMBus alert (Host or Device mode) + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note SMBus Device mode: + * - SMBus Alert pin is drived low and + * Alert Response Address Header acknowledge is enabled. + * SMBus Host mode: + * - SMBus Alert pin management is supported. + * @rmtoll CR1 ALERTEN LL_FMPI2C_EnableSMBusAlert + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableSMBusAlert(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ALERTEN); +} + +/** + * @brief Disable SMBus alert (Host or Device mode) + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note SMBus Device mode: + * - SMBus Alert pin is not drived (can be used as a standard GPIO) and + * Alert Response Address Header acknowledge is disabled. + * SMBus Host mode: + * - SMBus Alert pin management is not supported. + * @rmtoll CR1 ALERTEN LL_FMPI2C_DisableSMBusAlert + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableSMBusAlert(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ALERTEN); +} + +/** + * @brief Check if SMBus alert (Host or Device mode) is enabled or disabled. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 ALERTEN LL_FMPI2C_IsEnabledSMBusAlert + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledSMBusAlert(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ALERTEN) == (FMPI2C_CR1_ALERTEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable SMBus Packet Error Calculation (PEC). + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 PECEN LL_FMPI2C_EnableSMBusPEC + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableSMBusPEC(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PECEN); +} + +/** + * @brief Disable SMBus Packet Error Calculation (PEC). + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 PECEN LL_FMPI2C_DisableSMBusPEC + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableSMBusPEC(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PECEN); +} + +/** + * @brief Check if SMBus Packet Error Calculation (PEC) is enabled or disabled. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR1 PECEN LL_FMPI2C_IsEnabledSMBusPEC + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledSMBusPEC(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_PECEN) == (FMPI2C_CR1_PECEN)) ? 1UL : 0UL); +} + +/** + * @brief Configure the SMBus Clock Timeout. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note This configuration can only be programmed when associated Timeout is disabled (TimeoutA and/orTimeoutB). + * @rmtoll TIMEOUTR TIMEOUTA LL_FMPI2C_ConfigSMBusTimeout\n + * TIMEOUTR TIDLE LL_FMPI2C_ConfigSMBusTimeout\n + * TIMEOUTR TIMEOUTB LL_FMPI2C_ConfigSMBusTimeout + * @param FMPI2Cx FMPI2C Instance. + * @param TimeoutA This parameter must be a value between Min_Data=0 and Max_Data=0xFFF. + * @param TimeoutAMode This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + * @param TimeoutB + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ConfigSMBusTimeout(FMPI2C_TypeDef *FMPI2Cx, uint32_t TimeoutA, uint32_t TimeoutAMode, + uint32_t TimeoutB) +{ + MODIFY_REG(FMPI2Cx->TIMEOUTR, FMPI2C_TIMEOUTR_TIMEOUTA | FMPI2C_TIMEOUTR_TIDLE | FMPI2C_TIMEOUTR_TIMEOUTB, + TimeoutA | TimeoutAMode | (TimeoutB << FMPI2C_TIMEOUTR_TIMEOUTB_Pos)); +} + +/** + * @brief Configure the SMBus Clock TimeoutA (SCL low timeout or SCL and SDA high timeout depends on TimeoutA mode). + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note These bits can only be programmed when TimeoutA is disabled. + * @rmtoll TIMEOUTR TIMEOUTA LL_FMPI2C_SetSMBusTimeoutA + * @param FMPI2Cx FMPI2C Instance. + * @param TimeoutA This parameter must be a value between Min_Data=0 and Max_Data=0xFFF. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetSMBusTimeoutA(FMPI2C_TypeDef *FMPI2Cx, uint32_t TimeoutA) +{ + WRITE_REG(FMPI2Cx->TIMEOUTR, TimeoutA); +} + +/** + * @brief Get the SMBus Clock TimeoutA setting. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIMEOUTA LL_FMPI2C_GetSMBusTimeoutA + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetSMBusTimeoutA(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMEOUTR, FMPI2C_TIMEOUTR_TIMEOUTA)); +} + +/** + * @brief Set the SMBus Clock TimeoutA mode. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note This bit can only be programmed when TimeoutA is disabled. + * @rmtoll TIMEOUTR TIDLE LL_FMPI2C_SetSMBusTimeoutAMode + * @param FMPI2Cx FMPI2C Instance. + * @param TimeoutAMode This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetSMBusTimeoutAMode(FMPI2C_TypeDef *FMPI2Cx, uint32_t TimeoutAMode) +{ + WRITE_REG(FMPI2Cx->TIMEOUTR, TimeoutAMode); +} + +/** + * @brief Get the SMBus Clock TimeoutA mode. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIDLE LL_FMPI2C_GetSMBusTimeoutAMode + * @param FMPI2Cx FMPI2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SCL_LOW + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA_MODE_SDA_SCL_HIGH + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetSMBusTimeoutAMode(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMEOUTR, FMPI2C_TIMEOUTR_TIDLE)); +} + +/** + * @brief Configure the SMBus Extended Cumulative Clock TimeoutB (Master or Slave mode). + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note These bits can only be programmed when TimeoutB is disabled. + * @rmtoll TIMEOUTR TIMEOUTB LL_FMPI2C_SetSMBusTimeoutB + * @param FMPI2Cx FMPI2C Instance. + * @param TimeoutB This parameter must be a value between Min_Data=0 and Max_Data=0xFFF. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetSMBusTimeoutB(FMPI2C_TypeDef *FMPI2Cx, uint32_t TimeoutB) +{ + WRITE_REG(FMPI2Cx->TIMEOUTR, TimeoutB << FMPI2C_TIMEOUTR_TIMEOUTB_Pos); +} + +/** + * @brief Get the SMBus Extended Cumulative Clock TimeoutB setting. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIMEOUTB LL_FMPI2C_GetSMBusTimeoutB + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0 and Max_Data=0xFFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetSMBusTimeoutB(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->TIMEOUTR, FMPI2C_TIMEOUTR_TIMEOUTB) >> FMPI2C_TIMEOUTR_TIMEOUTB_Pos); +} + +/** + * @brief Enable the SMBus Clock Timeout. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_FMPI2C_EnableSMBusTimeout\n + * TIMEOUTR TEXTEN LL_FMPI2C_EnableSMBusTimeout + * @param FMPI2Cx FMPI2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTB + * @arg @ref LL_FMPI2C_FMPSMBUS_ALL_TIMEOUT + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableSMBusTimeout(FMPI2C_TypeDef *FMPI2Cx, uint32_t ClockTimeout) +{ + SET_BIT(FMPI2Cx->TIMEOUTR, ClockTimeout); +} + +/** + * @brief Disable the SMBus Clock Timeout. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_FMPI2C_DisableSMBusTimeout\n + * TIMEOUTR TEXTEN LL_FMPI2C_DisableSMBusTimeout + * @param FMPI2Cx FMPI2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTB + * @arg @ref LL_FMPI2C_FMPSMBUS_ALL_TIMEOUT + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableSMBusTimeout(FMPI2C_TypeDef *FMPI2Cx, uint32_t ClockTimeout) +{ + CLEAR_BIT(FMPI2Cx->TIMEOUTR, ClockTimeout); +} + +/** + * @brief Check if the SMBus Clock Timeout is enabled or disabled. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll TIMEOUTR TIMOUTEN LL_FMPI2C_IsEnabledSMBusTimeout\n + * TIMEOUTR TEXTEN LL_FMPI2C_IsEnabledSMBusTimeout + * @param FMPI2Cx FMPI2C Instance. + * @param ClockTimeout This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTA + * @arg @ref LL_FMPI2C_FMPSMBUS_TIMEOUTB + * @arg @ref LL_FMPI2C_FMPSMBUS_ALL_TIMEOUT + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledSMBusTimeout(FMPI2C_TypeDef *FMPI2Cx, uint32_t ClockTimeout) +{ + return ((READ_BIT(FMPI2Cx->TIMEOUTR, (FMPI2C_TIMEOUTR_TIMOUTEN | FMPI2C_TIMEOUTR_TEXTEN)) == \ + (ClockTimeout)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable TXIS interrupt. + * @rmtoll CR1 TXIE LL_FMPI2C_EnableIT_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXIE); +} + +/** + * @brief Disable TXIS interrupt. + * @rmtoll CR1 TXIE LL_FMPI2C_DisableIT_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXIE); +} + +/** + * @brief Check if the TXIS Interrupt is enabled or disabled. + * @rmtoll CR1 TXIE LL_FMPI2C_IsEnabledIT_TX + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_TX(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TXIE) == (FMPI2C_CR1_TXIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable RXNE interrupt. + * @rmtoll CR1 RXIE LL_FMPI2C_EnableIT_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXIE); +} + +/** + * @brief Disable RXNE interrupt. + * @rmtoll CR1 RXIE LL_FMPI2C_DisableIT_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXIE); +} + +/** + * @brief Check if the RXNE Interrupt is enabled or disabled. + * @rmtoll CR1 RXIE LL_FMPI2C_IsEnabledIT_RX + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_RX(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_RXIE) == (FMPI2C_CR1_RXIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Address match interrupt (slave mode only). + * @rmtoll CR1 ADDRIE LL_FMPI2C_EnableIT_ADDR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_ADDR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ADDRIE); +} + +/** + * @brief Disable Address match interrupt (slave mode only). + * @rmtoll CR1 ADDRIE LL_FMPI2C_DisableIT_ADDR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_ADDR(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ADDRIE); +} + +/** + * @brief Check if Address match interrupt is enabled or disabled. + * @rmtoll CR1 ADDRIE LL_FMPI2C_IsEnabledIT_ADDR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_ADDR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ADDRIE) == (FMPI2C_CR1_ADDRIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Not acknowledge received interrupt. + * @rmtoll CR1 NACKIE LL_FMPI2C_EnableIT_NACK + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_NACK(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NACKIE); +} + +/** + * @brief Disable Not acknowledge received interrupt. + * @rmtoll CR1 NACKIE LL_FMPI2C_DisableIT_NACK + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_NACK(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NACKIE); +} + +/** + * @brief Check if Not acknowledge received interrupt is enabled or disabled. + * @rmtoll CR1 NACKIE LL_FMPI2C_IsEnabledIT_NACK + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_NACK(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_NACKIE) == (FMPI2C_CR1_NACKIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable STOP detection interrupt. + * @rmtoll CR1 STOPIE LL_FMPI2C_EnableIT_STOP + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_STOP(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_STOPIE); +} + +/** + * @brief Disable STOP detection interrupt. + * @rmtoll CR1 STOPIE LL_FMPI2C_DisableIT_STOP + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_STOP(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_STOPIE); +} + +/** + * @brief Check if STOP detection interrupt is enabled or disabled. + * @rmtoll CR1 STOPIE LL_FMPI2C_IsEnabledIT_STOP + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_STOP(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_STOPIE) == (FMPI2C_CR1_STOPIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Transfer Complete interrupt. + * @note Any of these events will generate interrupt : + * Transfer Complete (TC) + * Transfer Complete Reload (TCR) + * @rmtoll CR1 TCIE LL_FMPI2C_EnableIT_TC + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_TC(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TCIE); +} + +/** + * @brief Disable Transfer Complete interrupt. + * @note Any of these events will generate interrupt : + * Transfer Complete (TC) + * Transfer Complete Reload (TCR) + * @rmtoll CR1 TCIE LL_FMPI2C_DisableIT_TC + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_TC(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TCIE); +} + +/** + * @brief Check if Transfer Complete interrupt is enabled or disabled. + * @rmtoll CR1 TCIE LL_FMPI2C_IsEnabledIT_TC + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_TC(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_TCIE) == (FMPI2C_CR1_TCIE)) ? 1UL : 0UL); +} + +/** + * @brief Enable Error interrupts. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note Any of these errors will generate interrupt : + * Arbitration Loss (ARLO) + * Bus Error detection (BERR) + * Overrun/Underrun (OVR) + * SMBus Timeout detection (TIMEOUT) + * SMBus PEC error detection (PECERR) + * SMBus Alert pin event detection (ALERT) + * @rmtoll CR1 ERRIE LL_FMPI2C_EnableIT_ERR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableIT_ERR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ERRIE); +} + +/** + * @brief Disable Error interrupts. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note Any of these errors will generate interrupt : + * Arbitration Loss (ARLO) + * Bus Error detection (BERR) + * Overrun/Underrun (OVR) + * SMBus Timeout detection (TIMEOUT) + * SMBus PEC error detection (PECERR) + * SMBus Alert pin event detection (ALERT) + * @rmtoll CR1 ERRIE LL_FMPI2C_DisableIT_ERR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableIT_ERR(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ERRIE); +} + +/** + * @brief Check if Error interrupts are enabled or disabled. + * @rmtoll CR1 ERRIE LL_FMPI2C_IsEnabledIT_ERR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledIT_ERR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR1, FMPI2C_CR1_ERRIE) == (FMPI2C_CR1_ERRIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EF_FLAG_management FLAG_management + * @{ + */ + +/** + * @brief Indicate the status of Transmit data register empty flag. + * @note RESET: When next data is written in Transmit data register. + * SET: When Transmit data register is empty. + * @rmtoll ISR TXE LL_FMPI2C_IsActiveFlag_TXE + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_TXE(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_TXE) == (FMPI2C_ISR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Transmit interrupt flag. + * @note RESET: When next data is written in Transmit data register. + * SET: When Transmit data register is empty. + * @rmtoll ISR TXIS LL_FMPI2C_IsActiveFlag_TXIS + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_TXIS(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_TXIS) == (FMPI2C_ISR_TXIS)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Receive data register not empty flag. + * @note RESET: When Receive data register is read. + * SET: When the received data is copied in Receive data register. + * @rmtoll ISR RXNE LL_FMPI2C_IsActiveFlag_RXNE + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_RXNE(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_RXNE) == (FMPI2C_ISR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Address matched flag (slave mode). + * @note RESET: Clear default value. + * SET: When the received slave address matched with one of the enabled slave address. + * @rmtoll ISR ADDR LL_FMPI2C_IsActiveFlag_ADDR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_ADDR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_ADDR) == (FMPI2C_ISR_ADDR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Not Acknowledge received flag. + * @note RESET: Clear default value. + * SET: When a NACK is received after a byte transmission. + * @rmtoll ISR NACKF LL_FMPI2C_IsActiveFlag_NACK + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_NACK(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_NACKF) == (FMPI2C_ISR_NACKF)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Stop detection flag. + * @note RESET: Clear default value. + * SET: When a Stop condition is detected. + * @rmtoll ISR STOPF LL_FMPI2C_IsActiveFlag_STOP + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_STOP(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_STOPF) == (FMPI2C_ISR_STOPF)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Transfer complete flag (master mode). + * @note RESET: Clear default value. + * SET: When RELOAD=0, AUTOEND=0 and NBYTES date have been transferred. + * @rmtoll ISR TC LL_FMPI2C_IsActiveFlag_TC + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_TC(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_TC) == (FMPI2C_ISR_TC)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Transfer complete flag (master mode). + * @note RESET: Clear default value. + * SET: When RELOAD=1 and NBYTES date have been transferred. + * @rmtoll ISR TCR LL_FMPI2C_IsActiveFlag_TCR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_TCR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_TCR) == (FMPI2C_ISR_TCR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Bus error flag. + * @note RESET: Clear default value. + * SET: When a misplaced Start or Stop condition is detected. + * @rmtoll ISR BERR LL_FMPI2C_IsActiveFlag_BERR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_BERR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_BERR) == (FMPI2C_ISR_BERR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Arbitration lost flag. + * @note RESET: Clear default value. + * SET: When arbitration lost. + * @rmtoll ISR ARLO LL_FMPI2C_IsActiveFlag_ARLO + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_ARLO(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_ARLO) == (FMPI2C_ISR_ARLO)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Overrun/Underrun flag (slave mode). + * @note RESET: Clear default value. + * SET: When an overrun/underrun error occurs (Clock Stretching Disabled). + * @rmtoll ISR OVR LL_FMPI2C_IsActiveFlag_OVR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_OVR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_OVR) == (FMPI2C_ISR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus PEC error flag in reception. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note RESET: Clear default value. + * SET: When the received PEC does not match with the PEC register content. + * @rmtoll ISR PECERR LL_FMPI2C_IsActiveSMBusFlag_PECERR + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveSMBusFlag_PECERR(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_PECERR) == (FMPI2C_ISR_PECERR)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus Timeout detection flag. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note RESET: Clear default value. + * SET: When a timeout or extended clock timeout occurs. + * @rmtoll ISR TIMEOUT LL_FMPI2C_IsActiveSMBusFlag_TIMEOUT + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveSMBusFlag_TIMEOUT(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_TIMEOUT) == (FMPI2C_ISR_TIMEOUT)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of SMBus alert flag. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note RESET: Clear default value. + * SET: When SMBus host configuration, SMBus alert enabled and + * a falling edge event occurs on SMBA pin. + * @rmtoll ISR ALERT LL_FMPI2C_IsActiveSMBusFlag_ALERT + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveSMBusFlag_ALERT(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_ALERT) == (FMPI2C_ISR_ALERT)) ? 1UL : 0UL); +} + +/** + * @brief Indicate the status of Bus Busy flag. + * @note RESET: Clear default value. + * SET: When a Start condition is detected. + * @rmtoll ISR BUSY LL_FMPI2C_IsActiveFlag_BUSY + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsActiveFlag_BUSY(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_BUSY) == (FMPI2C_ISR_BUSY)) ? 1UL : 0UL); +} + +/** + * @brief Clear Address Matched flag. + * @rmtoll ICR ADDRCF LL_FMPI2C_ClearFlag_ADDR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_ADDR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_ADDRCF); +} + +/** + * @brief Clear Not Acknowledge flag. + * @rmtoll ICR NACKCF LL_FMPI2C_ClearFlag_NACK + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_NACK(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_NACKCF); +} + +/** + * @brief Clear Stop detection flag. + * @rmtoll ICR STOPCF LL_FMPI2C_ClearFlag_STOP + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_STOP(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_STOPCF); +} + +/** + * @brief Clear Transmit data register empty flag (TXE). + * @note This bit can be clear by software in order to flush the transmit data register (TXDR). + * @rmtoll ISR TXE LL_FMPI2C_ClearFlag_TXE + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_TXE(FMPI2C_TypeDef *FMPI2Cx) +{ + WRITE_REG(FMPI2Cx->ISR, FMPI2C_ISR_TXE); +} + +/** + * @brief Clear Bus error flag. + * @rmtoll ICR BERRCF LL_FMPI2C_ClearFlag_BERR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_BERR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_BERRCF); +} + +/** + * @brief Clear Arbitration lost flag. + * @rmtoll ICR ARLOCF LL_FMPI2C_ClearFlag_ARLO + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_ARLO(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_ARLOCF); +} + +/** + * @brief Clear Overrun/Underrun flag. + * @rmtoll ICR OVRCF LL_FMPI2C_ClearFlag_OVR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearFlag_OVR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_OVRCF); +} + +/** + * @brief Clear SMBus PEC error flag. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll ICR PECCF LL_FMPI2C_ClearSMBusFlag_PECERR + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearSMBusFlag_PECERR(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_PECCF); +} + +/** + * @brief Clear SMBus Timeout detection flag. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll ICR TIMOUTCF LL_FMPI2C_ClearSMBusFlag_TIMEOUT + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearSMBusFlag_TIMEOUT(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_TIMOUTCF); +} + +/** + * @brief Clear SMBus Alert flag. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll ICR ALERTCF LL_FMPI2C_ClearSMBusFlag_ALERT + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_ClearSMBusFlag_ALERT(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->ICR, FMPI2C_ICR_ALERTCF); +} + +/** + * @} + */ + +/** @defgroup FMPI2C_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Enable automatic STOP condition generation (master mode). + * @note Automatic end mode : a STOP condition is automatically sent when NBYTES data are transferred. + * This bit has no effect in slave mode or when RELOAD bit is set. + * @rmtoll CR2 AUTOEND LL_FMPI2C_EnableAutoEndMode + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableAutoEndMode(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_AUTOEND); +} + +/** + * @brief Disable automatic STOP condition generation (master mode). + * @note Software end mode : TC flag is set when NBYTES data are transferre, stretching SCL low. + * @rmtoll CR2 AUTOEND LL_FMPI2C_DisableAutoEndMode + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableAutoEndMode(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR2, FMPI2C_CR2_AUTOEND); +} + +/** + * @brief Check if automatic STOP condition is enabled or disabled. + * @rmtoll CR2 AUTOEND LL_FMPI2C_IsEnabledAutoEndMode + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledAutoEndMode(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_AUTOEND) == (FMPI2C_CR2_AUTOEND)) ? 1UL : 0UL); +} + +/** + * @brief Enable reload mode (master mode). + * @note The transfer is not completed after the NBYTES data transfer, NBYTES will be reloaded when TCR flag is set. + * @rmtoll CR2 RELOAD LL_FMPI2C_EnableReloadMode + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableReloadMode(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_RELOAD); +} + +/** + * @brief Disable reload mode (master mode). + * @note The transfer is completed after the NBYTES data transfer(STOP or RESTART will follow). + * @rmtoll CR2 RELOAD LL_FMPI2C_DisableReloadMode + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableReloadMode(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR2, FMPI2C_CR2_RELOAD); +} + +/** + * @brief Check if reload mode is enabled or disabled. + * @rmtoll CR2 RELOAD LL_FMPI2C_IsEnabledReloadMode + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledReloadMode(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_RELOAD) == (FMPI2C_CR2_RELOAD)) ? 1UL : 0UL); +} + +/** + * @brief Configure the number of bytes for transfer. + * @note Changing these bits when START bit is set is not allowed. + * @rmtoll CR2 NBYTES LL_FMPI2C_SetTransferSize + * @param FMPI2Cx FMPI2C Instance. + * @param TransferSize This parameter must be a value between Min_Data=0x00 and Max_Data=0xFF. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetTransferSize(FMPI2C_TypeDef *FMPI2Cx, uint32_t TransferSize) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_NBYTES, TransferSize << FMPI2C_CR2_NBYTES_Pos); +} + +/** + * @brief Get the number of bytes configured for transfer. + * @rmtoll CR2 NBYTES LL_FMPI2C_GetTransferSize + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetTransferSize(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_NBYTES) >> FMPI2C_CR2_NBYTES_Pos); +} + +/** + * @brief Prepare the generation of a ACKnowledge or Non ACKnowledge condition after the address receive match code + or next received byte. + * @note Usage in Slave mode only. + * @rmtoll CR2 NACK LL_FMPI2C_AcknowledgeNextData + * @param FMPI2Cx FMPI2C Instance. + * @param TypeAcknowledge This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_ACK + * @arg @ref LL_FMPI2C_NACK + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_AcknowledgeNextData(FMPI2C_TypeDef *FMPI2Cx, uint32_t TypeAcknowledge) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_NACK, TypeAcknowledge); +} + +/** + * @brief Generate a START or RESTART condition + * @note The START bit can be set even if bus is BUSY or FMPI2C is in slave mode. + * This action has no effect when RELOAD is set. + * @rmtoll CR2 START LL_FMPI2C_GenerateStartCondition + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_GenerateStartCondition(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_START); +} + +/** + * @brief Generate a STOP condition after the current byte transfer (master mode). + * @rmtoll CR2 STOP LL_FMPI2C_GenerateStopCondition + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_GenerateStopCondition(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_STOP); +} + +/** + * @brief Enable automatic RESTART Read request condition for 10bit address header (master mode). + * @note The master sends the complete 10bit slave address read sequence : + * Start + 2 bytes 10bit address in Write direction + Restart + first 7 bits of 10bit address + in Read direction. + * @rmtoll CR2 HEAD10R LL_FMPI2C_EnableAuto10BitRead + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableAuto10BitRead(FMPI2C_TypeDef *FMPI2Cx) +{ + CLEAR_BIT(FMPI2Cx->CR2, FMPI2C_CR2_HEAD10R); +} + +/** + * @brief Disable automatic RESTART Read request condition for 10bit address header (master mode). + * @note The master only sends the first 7 bits of 10bit address in Read direction. + * @rmtoll CR2 HEAD10R LL_FMPI2C_DisableAuto10BitRead + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_DisableAuto10BitRead(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_HEAD10R); +} + +/** + * @brief Check if automatic RESTART Read request condition for 10bit address header is enabled or disabled. + * @rmtoll CR2 HEAD10R LL_FMPI2C_IsEnabledAuto10BitRead + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledAuto10BitRead(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_HEAD10R) != (FMPI2C_CR2_HEAD10R)) ? 1UL : 0UL); +} + +/** + * @brief Configure the transfer direction (master mode). + * @note Changing these bits when START bit is set is not allowed. + * @rmtoll CR2 RD_WRN LL_FMPI2C_SetTransferRequest + * @param FMPI2Cx FMPI2C Instance. + * @param TransferRequest This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_REQUEST_WRITE + * @arg @ref LL_FMPI2C_REQUEST_READ + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetTransferRequest(FMPI2C_TypeDef *FMPI2Cx, uint32_t TransferRequest) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_RD_WRN, TransferRequest); +} + +/** + * @brief Get the transfer direction requested (master mode). + * @rmtoll CR2 RD_WRN LL_FMPI2C_GetTransferRequest + * @param FMPI2Cx FMPI2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_FMPI2C_REQUEST_WRITE + * @arg @ref LL_FMPI2C_REQUEST_READ + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetTransferRequest(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_RD_WRN)); +} + +/** + * @brief Configure the slave address for transfer (master mode). + * @note Changing these bits when START bit is set is not allowed. + * @rmtoll CR2 SADD LL_FMPI2C_SetSlaveAddr + * @param FMPI2Cx FMPI2C Instance. + * @param SlaveAddr This parameter must be a value between Min_Data=0x00 and Max_Data=0x3F. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_SetSlaveAddr(FMPI2C_TypeDef *FMPI2Cx, uint32_t SlaveAddr) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_SADD, SlaveAddr); +} + +/** + * @brief Get the slave address programmed for transfer. + * @rmtoll CR2 SADD LL_FMPI2C_GetSlaveAddr + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0x3F + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetSlaveAddr(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_SADD)); +} + +/** + * @brief Handles FMPI2Cx communication when starting transfer or during transfer (TC or TCR flag are set). + * @rmtoll CR2 SADD LL_FMPI2C_HandleTransfer\n + * CR2 ADD10 LL_FMPI2C_HandleTransfer\n + * CR2 RD_WRN LL_FMPI2C_HandleTransfer\n + * CR2 START LL_FMPI2C_HandleTransfer\n + * CR2 STOP LL_FMPI2C_HandleTransfer\n + * CR2 RELOAD LL_FMPI2C_HandleTransfer\n + * CR2 NBYTES LL_FMPI2C_HandleTransfer\n + * CR2 AUTOEND LL_FMPI2C_HandleTransfer\n + * CR2 HEAD10R LL_FMPI2C_HandleTransfer + * @param FMPI2Cx FMPI2C Instance. + * @param SlaveAddr Specifies the slave address to be programmed. + * @param SlaveAddrSize This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_ADDRSLAVE_7BIT + * @arg @ref LL_FMPI2C_ADDRSLAVE_10BIT + * @param TransferSize Specifies the number of bytes to be programmed. + * This parameter must be a value between Min_Data=0 and Max_Data=255. + * @param EndMode This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_MODE_RELOAD + * @arg @ref LL_FMPI2C_MODE_AUTOEND + * @arg @ref LL_FMPI2C_MODE_SOFTEND + * @arg @ref LL_FMPI2C_MODE_SMBUS_RELOAD + * @arg @ref LL_FMPI2C_MODE_SMBUS_AUTOEND_NO_PEC + * @arg @ref LL_FMPI2C_MODE_SMBUS_SOFTEND_NO_PEC + * @arg @ref LL_FMPI2C_MODE_SMBUS_AUTOEND_WITH_PEC + * @arg @ref LL_FMPI2C_MODE_SMBUS_SOFTEND_WITH_PEC + * @param Request This parameter can be one of the following values: + * @arg @ref LL_FMPI2C_GENERATE_NOSTARTSTOP + * @arg @ref LL_FMPI2C_GENERATE_STOP + * @arg @ref LL_FMPI2C_GENERATE_START_READ + * @arg @ref LL_FMPI2C_GENERATE_START_WRITE + * @arg @ref LL_FMPI2C_GENERATE_RESTART_7BIT_READ + * @arg @ref LL_FMPI2C_GENERATE_RESTART_7BIT_WRITE + * @arg @ref LL_FMPI2C_GENERATE_RESTART_10BIT_READ + * @arg @ref LL_FMPI2C_GENERATE_RESTART_10BIT_WRITE + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_HandleTransfer(FMPI2C_TypeDef *FMPI2Cx, uint32_t SlaveAddr, uint32_t SlaveAddrSize, + uint32_t TransferSize, uint32_t EndMode, uint32_t Request) +{ + MODIFY_REG(FMPI2Cx->CR2, FMPI2C_CR2_SADD | FMPI2C_CR2_ADD10 | + (FMPI2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - FMPI2C_CR2_RD_WRN_Pos))) | + FMPI2C_CR2_START | FMPI2C_CR2_STOP | FMPI2C_CR2_RELOAD | + FMPI2C_CR2_NBYTES | FMPI2C_CR2_AUTOEND | FMPI2C_CR2_HEAD10R, + SlaveAddr | SlaveAddrSize | (TransferSize << FMPI2C_CR2_NBYTES_Pos) | EndMode | Request); +} + +/** + * @brief Indicate the value of transfer direction (slave mode). + * @note RESET: Write transfer, Slave enters in receiver mode. + * SET: Read transfer, Slave enters in transmitter mode. + * @rmtoll ISR DIR LL_FMPI2C_GetTransferDirection + * @param FMPI2Cx FMPI2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_FMPI2C_DIRECTION_WRITE + * @arg @ref LL_FMPI2C_DIRECTION_READ + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetTransferDirection(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_DIR)); +} + +/** + * @brief Return the slave matched address. + * @rmtoll ISR ADDCODE LL_FMPI2C_GetAddressMatchCode + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0x3F + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetAddressMatchCode(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->ISR, FMPI2C_ISR_ADDCODE) >> FMPI2C_ISR_ADDCODE_Pos << 1); +} + +/** + * @brief Enable internal comparison of the SMBus Packet Error byte (transmission or reception mode). + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @note This feature is cleared by hardware when the PEC byte is transferred, or when a STOP condition + or an Address Matched is received. + * This bit has no effect when RELOAD bit is set. + * This bit has no effect in device mode when SBC bit is not set. + * @rmtoll CR2 PECBYTE LL_FMPI2C_EnableSMBusPECCompare + * @param FMPI2Cx FMPI2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_EnableSMBusPECCompare(FMPI2C_TypeDef *FMPI2Cx) +{ + SET_BIT(FMPI2Cx->CR2, FMPI2C_CR2_PECBYTE); +} + +/** + * @brief Check if the SMBus Packet Error byte internal comparison is requested or not. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll CR2 PECBYTE LL_FMPI2C_IsEnabledSMBusPECCompare + * @param FMPI2Cx FMPI2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_FMPI2C_IsEnabledSMBusPECCompare(FMPI2C_TypeDef *FMPI2Cx) +{ + return ((READ_BIT(FMPI2Cx->CR2, FMPI2C_CR2_PECBYTE) == (FMPI2C_CR2_PECBYTE)) ? 1UL : 0UL); +} + +/** + * @brief Get the SMBus Packet Error byte calculated. + * @note The macro IS_FMPSMBUS_ALL_INSTANCE(FMPI2Cx) can be used to check whether or not + * SMBus feature is supported by the FMPI2Cx Instance. + * @rmtoll PECR PEC LL_FMPI2C_GetSMBusPEC + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_FMPI2C_GetSMBusPEC(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint32_t)(READ_BIT(FMPI2Cx->PECR, FMPI2C_PECR_PEC)); +} + +/** + * @brief Read Receive Data register. + * @rmtoll RXDR RXDATA LL_FMPI2C_ReceiveData8 + * @param FMPI2Cx FMPI2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_FMPI2C_ReceiveData8(FMPI2C_TypeDef *FMPI2Cx) +{ + return (uint8_t)(READ_BIT(FMPI2Cx->RXDR, FMPI2C_RXDR_RXDATA)); +} + +/** + * @brief Write in Transmit Data Register . + * @rmtoll TXDR TXDATA LL_FMPI2C_TransmitData8 + * @param FMPI2Cx FMPI2C Instance. + * @param Data Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_FMPI2C_TransmitData8(FMPI2C_TypeDef *FMPI2Cx, uint8_t Data) +{ + WRITE_REG(FMPI2Cx->TXDR, Data); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup FMPI2C_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_FMPI2C_Init(FMPI2C_TypeDef *FMPI2Cx, LL_FMPI2C_InitTypeDef *FMPI2C_InitStruct); +ErrorStatus LL_FMPI2C_DeInit(FMPI2C_TypeDef *FMPI2Cx); +void LL_FMPI2C_StructInit(LL_FMPI2C_InitTypeDef *FMPI2C_InitStruct); + + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C1 */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_FMPI2C_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h new file mode 100644 index 0000000..8b0ceb7 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_fsmc.h @@ -0,0 +1,1086 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fsmc.h + * @author MCD Application Team + * @brief Header file of FSMC 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 STM32F4xx_LL_FSMC_H +#define STM32F4xx_LL_FSMC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup FSMC_LL + * @{ + */ + +/** @addtogroup FSMC_LL_Private_Macros + * @{ + */ +#if defined(FSMC_Bank1) + +#define IS_FSMC_NORSRAM_BANK(__BANK__) (((__BANK__) == FSMC_NORSRAM_BANK1) || \ + ((__BANK__) == FSMC_NORSRAM_BANK2) || \ + ((__BANK__) == FSMC_NORSRAM_BANK3) || \ + ((__BANK__) == FSMC_NORSRAM_BANK4)) +#define IS_FSMC_MUX(__MUX__) (((__MUX__) == FSMC_DATA_ADDRESS_MUX_DISABLE) || \ + ((__MUX__) == FSMC_DATA_ADDRESS_MUX_ENABLE)) +#define IS_FSMC_MEMORY(__MEMORY__) (((__MEMORY__) == FSMC_MEMORY_TYPE_SRAM) || \ + ((__MEMORY__) == FSMC_MEMORY_TYPE_PSRAM)|| \ + ((__MEMORY__) == FSMC_MEMORY_TYPE_NOR)) +#define IS_FSMC_NORSRAM_MEMORY_WIDTH(__WIDTH__) (((__WIDTH__) == FSMC_NORSRAM_MEM_BUS_WIDTH_8) || \ + ((__WIDTH__) == FSMC_NORSRAM_MEM_BUS_WIDTH_16) || \ + ((__WIDTH__) == FSMC_NORSRAM_MEM_BUS_WIDTH_32)) +#define IS_FSMC_PAGESIZE(__SIZE__) (((__SIZE__) == FSMC_PAGE_SIZE_NONE) || \ + ((__SIZE__) == FSMC_PAGE_SIZE_128) || \ + ((__SIZE__) == FSMC_PAGE_SIZE_256) || \ + ((__SIZE__) == FSMC_PAGE_SIZE_512) || \ + ((__SIZE__) == FSMC_PAGE_SIZE_1024)) +#if defined(FSMC_BCR1_WFDIS) +#define IS_FSMC_WRITE_FIFO(__FIFO__) (((__FIFO__) == FSMC_WRITE_FIFO_DISABLE) || \ + ((__FIFO__) == FSMC_WRITE_FIFO_ENABLE)) +#endif /* FSMC_BCR1_WFDIS */ +#define IS_FSMC_ACCESS_MODE(__MODE__) (((__MODE__) == FSMC_ACCESS_MODE_A) || \ + ((__MODE__) == FSMC_ACCESS_MODE_B) || \ + ((__MODE__) == FSMC_ACCESS_MODE_C) || \ + ((__MODE__) == FSMC_ACCESS_MODE_D)) +#define IS_FSMC_BURSTMODE(__STATE__) (((__STATE__) == FSMC_BURST_ACCESS_MODE_DISABLE) || \ + ((__STATE__) == FSMC_BURST_ACCESS_MODE_ENABLE)) +#define IS_FSMC_WAIT_POLARITY(__POLARITY__) (((__POLARITY__) == FSMC_WAIT_SIGNAL_POLARITY_LOW) || \ + ((__POLARITY__) == FSMC_WAIT_SIGNAL_POLARITY_HIGH)) +#define IS_FSMC_WRAP_MODE(__MODE__) (((__MODE__) == FSMC_WRAP_MODE_DISABLE) || \ + ((__MODE__) == FSMC_WRAP_MODE_ENABLE)) +#define IS_FSMC_WAIT_SIGNAL_ACTIVE(__ACTIVE__) (((__ACTIVE__) == FSMC_WAIT_TIMING_BEFORE_WS) || \ + ((__ACTIVE__) == FSMC_WAIT_TIMING_DURING_WS)) +#define IS_FSMC_WRITE_OPERATION(__OPERATION__) (((__OPERATION__) == FSMC_WRITE_OPERATION_DISABLE) || \ + ((__OPERATION__) == FSMC_WRITE_OPERATION_ENABLE)) +#define IS_FSMC_WAITE_SIGNAL(__SIGNAL__) (((__SIGNAL__) == FSMC_WAIT_SIGNAL_DISABLE) || \ + ((__SIGNAL__) == FSMC_WAIT_SIGNAL_ENABLE)) +#define IS_FSMC_EXTENDED_MODE(__MODE__) (((__MODE__) == FSMC_EXTENDED_MODE_DISABLE) || \ + ((__MODE__) == FSMC_EXTENDED_MODE_ENABLE)) +#define IS_FSMC_ASYNWAIT(__STATE__) (((__STATE__) == FSMC_ASYNCHRONOUS_WAIT_DISABLE) || \ + ((__STATE__) == FSMC_ASYNCHRONOUS_WAIT_ENABLE)) +#define IS_FSMC_DATA_LATENCY(__LATENCY__) (((__LATENCY__) > 1U) && ((__LATENCY__) <= 17U)) +#define IS_FSMC_WRITE_BURST(__BURST__) (((__BURST__) == FSMC_WRITE_BURST_DISABLE) || \ + ((__BURST__) == FSMC_WRITE_BURST_ENABLE)) +#define IS_FSMC_CONTINOUS_CLOCK(__CCLOCK__) (((__CCLOCK__) == FSMC_CONTINUOUS_CLOCK_SYNC_ONLY) || \ + ((__CCLOCK__) == FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC)) +#define IS_FSMC_ADDRESS_SETUP_TIME(__TIME__) ((__TIME__) <= 15U) +#define IS_FSMC_ADDRESS_HOLD_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 15U)) +#define IS_FSMC_DATASETUP_TIME(__TIME__) (((__TIME__) > 0U) && ((__TIME__) <= 255U)) +#define IS_FSMC_DATAHOLD_DURATION(__DATAHOLD__) ((__DATAHOLD__) <= 3U) +#define IS_FSMC_TURNAROUND_TIME(__TIME__) ((__TIME__) <= 15U) +#define IS_FSMC_CLK_DIV(__DIV__) (((__DIV__) > 1U) && ((__DIV__) <= 16U)) +#define IS_FSMC_NORSRAM_DEVICE(__INSTANCE__) ((__INSTANCE__) == FSMC_NORSRAM_DEVICE) +#define IS_FSMC_NORSRAM_EXTENDED_DEVICE(__INSTANCE__) ((__INSTANCE__) == FSMC_NORSRAM_EXTENDED_DEVICE) + +#endif /* FSMC_Bank1 */ +#if defined(FSMC_Bank2_3) + +#define IS_FSMC_NAND_BANK(__BANK__) (((__BANK__) == FSMC_NAND_BANK2) || \ + ((__BANK__) == FSMC_NAND_BANK3)) +#define IS_FSMC_WAIT_FEATURE(__FEATURE__) (((__FEATURE__) == FSMC_NAND_PCC_WAIT_FEATURE_DISABLE) || \ + ((__FEATURE__) == FSMC_NAND_PCC_WAIT_FEATURE_ENABLE)) +#define IS_FSMC_NAND_MEMORY_WIDTH(__WIDTH__) (((__WIDTH__) == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) || \ + ((__WIDTH__) == FSMC_NAND_PCC_MEM_BUS_WIDTH_16)) +#define IS_FSMC_ECC_STATE(__STATE__) (((__STATE__) == FSMC_NAND_ECC_DISABLE) || \ + ((__STATE__) == FSMC_NAND_ECC_ENABLE)) + +#define IS_FSMC_ECCPAGE_SIZE(__SIZE__) (((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_256BYTE) || \ + ((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_512BYTE) || \ + ((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_1024BYTE) || \ + ((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_2048BYTE) || \ + ((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_4096BYTE) || \ + ((__SIZE__) == FSMC_NAND_ECC_PAGE_SIZE_8192BYTE)) +#define IS_FSMC_TCLR_TIME(__TIME__) ((__TIME__) <= 255U) +#define IS_FSMC_TAR_TIME(__TIME__) ((__TIME__) <= 255U) +#define IS_FSMC_SETUP_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FSMC_WAIT_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FSMC_HOLD_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FSMC_HIZ_TIME(__TIME__) ((__TIME__) <= 254U) +#define IS_FSMC_NAND_DEVICE(__INSTANCE__) ((__INSTANCE__) == FSMC_NAND_DEVICE) + +#endif /* FSMC_Bank2_3 */ +#if defined(FSMC_Bank4) +#define IS_FSMC_PCCARD_DEVICE(__INSTANCE__) ((__INSTANCE__) == FSMC_PCCARD_DEVICE) + +#endif /* FSMC_Bank4 */ + +/** + * @} + */ + +/* Exported typedef ----------------------------------------------------------*/ + +/** @defgroup FSMC_LL_Exported_typedef FSMC Low Layer Exported Types + * @{ + */ + +#if defined(FSMC_Bank1) +#define FSMC_NORSRAM_TypeDef FSMC_Bank1_TypeDef +#define FSMC_NORSRAM_EXTENDED_TypeDef FSMC_Bank1E_TypeDef +#endif /* FSMC_Bank1 */ +#if defined(FSMC_Bank2_3) +#define FSMC_NAND_TypeDef FSMC_Bank2_3_TypeDef +#endif /* FSMC_Bank2_3 */ +#if defined(FSMC_Bank4) +#define FSMC_PCCARD_TypeDef FSMC_Bank4_TypeDef +#endif /* FSMC_Bank4 */ + +#if defined(FSMC_Bank1) +#define FSMC_NORSRAM_DEVICE FSMC_Bank1 +#define FSMC_NORSRAM_EXTENDED_DEVICE FSMC_Bank1E +#endif /* FSMC_Bank1 */ +#if defined(FSMC_Bank2_3) +#define FSMC_NAND_DEVICE FSMC_Bank2_3 +#endif /* FSMC_Bank2_3 */ +#if defined(FSMC_Bank4) +#define FSMC_PCCARD_DEVICE FSMC_Bank4 +#endif /* FSMC_Bank4 */ + +#if defined(FSMC_Bank1) +/** + * @brief FSMC NORSRAM Configuration Structure definition + */ +typedef struct +{ + uint32_t NSBank; /*!< Specifies the NORSRAM memory device that will be used. + This parameter can be a value of @ref FSMC_NORSRAM_Bank */ + + uint32_t DataAddressMux; /*!< Specifies whether the address and data values are + multiplexed on the data bus or not. + This parameter can be a value of @ref FSMC_Data_Address_Bus_Multiplexing */ + + uint32_t MemoryType; /*!< Specifies the type of external memory attached to + the corresponding memory device. + This parameter can be a value of @ref FSMC_Memory_Type */ + + uint32_t MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be a value of @ref FSMC_NORSRAM_Data_Width */ + + uint32_t BurstAccessMode; /*!< Enables or disables the burst access mode for Flash memory, + valid only with synchronous burst Flash memories. + This parameter can be a value of @ref FSMC_Burst_Access_Mode */ + + uint32_t WaitSignalPolarity; /*!< Specifies the wait signal polarity, valid only when accessing + the Flash memory in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal_Polarity */ + + uint32_t WrapMode; /*!< Enables or disables the Wrapped burst access mode for Flash + memory, valid only when accessing Flash memories in burst mode. + This parameter can be a value of @ref FSMC_Wrap_Mode + This mode is available only for the STM32F405/407/4015/417xx devices */ + + uint32_t WaitSignalActive; /*!< Specifies if the wait signal is asserted by the memory one + clock cycle before the wait state or during the wait state, + valid only when accessing memories in burst mode. + This parameter can be a value of @ref FSMC_Wait_Timing */ + + uint32_t WriteOperation; /*!< Enables or disables the write operation in the selected device by the FSMC. + This parameter can be a value of @ref FSMC_Write_Operation */ + + uint32_t WaitSignal; /*!< Enables or disables the wait state insertion via wait + signal, valid for Flash memory access in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal */ + + uint32_t ExtendedMode; /*!< Enables or disables the extended mode. + This parameter can be a value of @ref FSMC_Extended_Mode */ + + uint32_t AsynchronousWait; /*!< Enables or disables wait signal during asynchronous transfers, + valid only with asynchronous Flash memories. + This parameter can be a value of @ref FSMC_AsynchronousWait */ + + uint32_t WriteBurst; /*!< Enables or disables the write burst operation. + This parameter can be a value of @ref FSMC_Write_Burst */ + + uint32_t ContinuousClock; /*!< Enables or disables the FSMC clock output to external memory devices. + This parameter is only enabled through the FSMC_BCR1 register, + and don't care through FSMC_BCR2..4 registers. + This parameter can be a value of @ref FSMC_Continous_Clock + This mode is available only for the STM32F412Vx/Zx/Rx devices */ + + uint32_t WriteFifo; /*!< Enables or disables the write FIFO used by the FSMC controller. + This parameter is only enabled through the FSMC_BCR1 register, + and don't care through FSMC_BCR2..4 registers. + This parameter can be a value of @ref FSMC_Write_FIFO + This mode is available only for the STM32F412Vx/Vx devices */ + + uint32_t PageSize; /*!< Specifies the memory page size. + This parameter can be a value of @ref FSMC_Page_Size */ +} FSMC_NORSRAM_InitTypeDef; + +/** + * @brief FSMC NORSRAM Timing parameters structure definition + */ +typedef struct +{ + uint32_t AddressSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address setup time. + This parameter can be a value between Min_Data = 0 and Max_Data = 15. + @note This parameter is not used with synchronous NOR Flash memories. */ + + uint32_t AddressHoldTime; /*!< Defines the number of HCLK cycles to configure + the duration of the address hold time. + This parameter can be a value between Min_Data = 1 and Max_Data = 15. + @note This parameter is not used with synchronous NOR Flash memories. */ + + uint32_t DataSetupTime; /*!< Defines the number of HCLK cycles to configure + the duration of the data setup time. + This parameter can be a value between Min_Data = 1 and Max_Data = 255. + @note This parameter is used for SRAMs, ROMs and asynchronous multiplexed + NOR Flash memories. */ + + uint32_t BusTurnAroundDuration; /*!< Defines the number of HCLK cycles to configure + the duration of the bus turnaround. + This parameter can be a value between Min_Data = 0 and Max_Data = 15. + @note This parameter is only used for multiplexed NOR Flash memories. */ + + uint32_t CLKDivision; /*!< Defines the period of CLK clock output signal, expressed in number of + HCLK cycles. This parameter can be a value between Min_Data = 2 and + Max_Data = 16. + @note This parameter is not used for asynchronous NOR Flash, SRAM or ROM + accesses. */ + + uint32_t DataLatency; /*!< Defines the number of memory clock cycles to issue + to the memory before getting the first data. + The parameter value depends on the memory type as shown below: + - It must be set to 0 in case of a CRAM + - It is don't care in asynchronous NOR, SRAM or ROM accesses + - It may assume a value between Min_Data = 2 and Max_Data = 17 + in NOR Flash memories with synchronous burst mode enable */ + + uint32_t AccessMode; /*!< Specifies the asynchronous access mode. + This parameter can be a value of @ref FSMC_Access_Mode */ +} FSMC_NORSRAM_TimingTypeDef; +#endif /* FSMC_Bank1 */ + +#if defined(FSMC_Bank2_3) +/** + * @brief FSMC NAND Configuration Structure definition + */ +typedef struct +{ + uint32_t NandBank; /*!< Specifies the NAND memory device that will be used. + This parameter can be a value of @ref FSMC_NAND_Bank */ + + uint32_t Waitfeature; /*!< Enables or disables the Wait feature for the NAND Memory device. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t MemoryDataWidth; /*!< Specifies the external memory device width. + This parameter can be any value of @ref FSMC_NAND_Data_Width */ + + uint32_t EccComputation; /*!< Enables or disables the ECC computation. + This parameter can be any value of @ref FSMC_ECC */ + + uint32_t ECCPageSize; /*!< Defines the page size for the extended ECC. + This parameter can be any value of @ref FSMC_ECC_Page_Size */ + + uint32_t TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between Min_Data = 0 and Max_Data = 255 */ + + uint32_t TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between Min_Data = 0 and Max_Data = 255 */ +} FSMC_NAND_InitTypeDef; +#endif + +#if defined(FSMC_Bank2_3) || defined(FSMC_Bank4) +/** + * @brief FSMC NAND Timing parameters structure definition + */ +typedef struct +{ + uint32_t SetupTime; /*!< Defines the number of HCLK cycles to setup address before + the command assertion for NAND-Flash read or write access + to common/Attribute or I/O memory space (depending on + the memory space timing to be configured). + This parameter can be a value between Min_Data = 0 and Max_Data = 254 */ + + uint32_t WaitSetupTime; /*!< Defines the minimum number of HCLK cycles to assert the + command for NAND-Flash read or write access to + common/Attribute or I/O memory space (depending on the + memory space timing to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ + + uint32_t HoldSetupTime; /*!< Defines the number of HCLK clock cycles to hold address + (and data for write access) after the command de-assertion + for NAND-Flash read or write access to common/Attribute + or I/O memory space (depending on the memory space timing + to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ + + uint32_t HiZSetupTime; /*!< Defines the number of HCLK clock cycles during which the + data bus is kept in HiZ after the start of a NAND-Flash + write access to common/Attribute or I/O memory space (depending + on the memory space timing to be configured). + This parameter can be a number between Min_Data = 0 and Max_Data = 254 */ +} FSMC_NAND_PCC_TimingTypeDef; +#endif /* FSMC_Bank2_3 */ + +#if defined(FSMC_Bank4) +/** + * @brief FSMC PCCARD Configuration Structure definition + */ +typedef struct +{ + uint32_t Waitfeature; /*!< Enables or disables the Wait feature for the PCCARD Memory device. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between Min_Data = 0 and Max_Data = 255 */ + + uint32_t TARSetupTime; /*!< Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between Min_Data = 0 and Max_Data = 255 */ +}FSMC_PCCARD_InitTypeDef; +#endif /* FSMC_Bank4 */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @addtogroup FSMC_LL_Exported_Constants FSMC Low Layer Exported Constants + * @{ + */ +#if defined(FSMC_Bank1) + +/** @defgroup FSMC_LL_NOR_SRAM_Controller FSMC NOR/SRAM Controller + * @{ + */ + +/** @defgroup FSMC_NORSRAM_Bank FSMC NOR/SRAM Bank + * @{ + */ +#define FSMC_NORSRAM_BANK1 (0x00000000U) +#define FSMC_NORSRAM_BANK2 (0x00000002U) +#define FSMC_NORSRAM_BANK3 (0x00000004U) +#define FSMC_NORSRAM_BANK4 (0x00000006U) +/** + * @} + */ + +/** @defgroup FSMC_Data_Address_Bus_Multiplexing FSMC Data Address Bus Multiplexing + * @{ + */ +#define FSMC_DATA_ADDRESS_MUX_DISABLE (0x00000000U) +#define FSMC_DATA_ADDRESS_MUX_ENABLE (0x00000002U) +/** + * @} + */ + +/** @defgroup FSMC_Memory_Type FSMC Memory Type + * @{ + */ +#define FSMC_MEMORY_TYPE_SRAM (0x00000000U) +#define FSMC_MEMORY_TYPE_PSRAM (0x00000004U) +#define FSMC_MEMORY_TYPE_NOR (0x00000008U) +/** + * @} + */ + +/** @defgroup FSMC_NORSRAM_Data_Width FSMC NORSRAM Data Width + * @{ + */ +#define FSMC_NORSRAM_MEM_BUS_WIDTH_8 (0x00000000U) +#define FSMC_NORSRAM_MEM_BUS_WIDTH_16 (0x00000010U) +#define FSMC_NORSRAM_MEM_BUS_WIDTH_32 (0x00000020U) +/** + * @} + */ + +/** @defgroup FSMC_NORSRAM_Flash_Access FSMC NOR/SRAM Flash Access + * @{ + */ +#define FSMC_NORSRAM_FLASH_ACCESS_ENABLE (0x00000040U) +#define FSMC_NORSRAM_FLASH_ACCESS_DISABLE (0x00000000U) +/** + * @} + */ + +/** @defgroup FSMC_Burst_Access_Mode FSMC Burst Access Mode + * @{ + */ +#define FSMC_BURST_ACCESS_MODE_DISABLE (0x00000000U) +#define FSMC_BURST_ACCESS_MODE_ENABLE (0x00000100U) +/** + * @} + */ + +/** @defgroup FSMC_Wait_Signal_Polarity FSMC Wait Signal Polarity + * @{ + */ +#define FSMC_WAIT_SIGNAL_POLARITY_LOW (0x00000000U) +#define FSMC_WAIT_SIGNAL_POLARITY_HIGH (0x00000200U) +/** + * @} + */ + +/** @defgroup FSMC_Wrap_Mode FSMC Wrap Mode + * @note These values are available only for the STM32F405/415/407/417xx devices. + * @{ + */ +#define FSMC_WRAP_MODE_DISABLE (0x00000000U) +#define FSMC_WRAP_MODE_ENABLE (0x00000400U) +/** + * @} + */ + +/** @defgroup FSMC_Wait_Timing FSMC Wait Timing + * @{ + */ +#define FSMC_WAIT_TIMING_BEFORE_WS (0x00000000U) +#define FSMC_WAIT_TIMING_DURING_WS (0x00000800U) +/** + * @} + */ + +/** @defgroup FSMC_Write_Operation FSMC Write Operation + * @{ + */ +#define FSMC_WRITE_OPERATION_DISABLE (0x00000000U) +#define FSMC_WRITE_OPERATION_ENABLE (0x00001000U) +/** + * @} + */ + +/** @defgroup FSMC_Wait_Signal FSMC Wait Signal + * @{ + */ +#define FSMC_WAIT_SIGNAL_DISABLE (0x00000000U) +#define FSMC_WAIT_SIGNAL_ENABLE (0x00002000U) +/** + * @} + */ + +/** @defgroup FSMC_Extended_Mode FSMC Extended Mode + * @{ + */ +#define FSMC_EXTENDED_MODE_DISABLE (0x00000000U) +#define FSMC_EXTENDED_MODE_ENABLE (0x00004000U) +/** + * @} + */ + +/** @defgroup FSMC_AsynchronousWait FSMC Asynchronous Wait + * @{ + */ +#define FSMC_ASYNCHRONOUS_WAIT_DISABLE (0x00000000U) +#define FSMC_ASYNCHRONOUS_WAIT_ENABLE (0x00008000U) +/** + * @} + */ + +/** @defgroup FSMC_Page_Size FSMC Page Size + * @{ + */ +#define FSMC_PAGE_SIZE_NONE (0x00000000U) +#define FSMC_PAGE_SIZE_128 FSMC_BCR1_CPSIZE_0 +#define FSMC_PAGE_SIZE_256 FSMC_BCR1_CPSIZE_1 +#define FSMC_PAGE_SIZE_512 (FSMC_BCR1_CPSIZE_0\ + | FSMC_BCR1_CPSIZE_1) +#define FSMC_PAGE_SIZE_1024 FSMC_BCR1_CPSIZE_2 +/** + * @} + */ + +/** @defgroup FSMC_Write_Burst FSMC Write Burst + * @{ + */ +#define FSMC_WRITE_BURST_DISABLE (0x00000000U) +#define FSMC_WRITE_BURST_ENABLE (0x00080000U) +/** + * @} + */ + +/** @defgroup FSMC_Continous_Clock FSMC Continuous Clock + * @note These values are available only for the STM32F412Vx/Zx/Rx devices. + * @{ + */ +#define FSMC_CONTINUOUS_CLOCK_SYNC_ONLY (0x00000000U) +#define FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC (0x00100000U) +/** + * @} + */ + +#if defined(FSMC_BCR1_WFDIS) +/** @defgroup FSMC_Write_FIFO FSMC Write FIFO + * @note These values are available only for the STM32F412Vx/Zx/Rx devices. + * @{ + */ +#define FSMC_WRITE_FIFO_DISABLE FSMC_BCR1_WFDIS +#define FSMC_WRITE_FIFO_ENABLE (0x00000000U) +#endif /* FSMC_BCR1_WFDIS */ +/** + * @} + */ + +/** @defgroup FSMC_Access_Mode FSMC Access Mode + * @{ + */ +#define FSMC_ACCESS_MODE_A (0x00000000U) +#define FSMC_ACCESS_MODE_B (0x10000000U) +#define FSMC_ACCESS_MODE_C (0x20000000U) +#define FSMC_ACCESS_MODE_D (0x30000000U) +/** + * @} + */ + +/** + * @} + */ +#endif /* FSMC_Bank1 */ + +#if defined(FSMC_Bank2_3) || defined(FSMC_Bank4) + +/** @defgroup FSMC_LL_NAND_Controller FSMC NAND Controller + * @{ + */ +/** @defgroup FSMC_NAND_Bank FSMC NAND Bank + * @{ + */ +#if defined(FSMC_Bank2_3) +#define FSMC_NAND_BANK2 (0x00000010U) +#endif +#define FSMC_NAND_BANK3 (0x00000100U) +/** + * @} + */ + +/** @defgroup FSMC_Wait_feature FSMC Wait feature + * @{ + */ +#define FSMC_NAND_PCC_WAIT_FEATURE_DISABLE (0x00000000U) +#define FSMC_NAND_PCC_WAIT_FEATURE_ENABLE (0x00000002U) +/** + * @} + */ + +/** @defgroup FSMC_PCR_Memory_Type FSMC PCR Memory Type + * @{ + */ +#if defined(FSMC_Bank4) +#define FSMC_PCR_MEMORY_TYPE_PCCARD (0x00000000U) +#endif /* FSMC_Bank4 */ +#define FSMC_PCR_MEMORY_TYPE_NAND (0x00000008U) +/** + * @} + */ + +/** @defgroup FSMC_NAND_Data_Width FSMC NAND Data Width + * @{ + */ +#define FSMC_NAND_PCC_MEM_BUS_WIDTH_8 (0x00000000U) +#define FSMC_NAND_PCC_MEM_BUS_WIDTH_16 (0x00000010U) +/** + * @} + */ + +/** @defgroup FSMC_ECC FSMC ECC + * @{ + */ +#define FSMC_NAND_ECC_DISABLE (0x00000000U) +#define FSMC_NAND_ECC_ENABLE (0x00000040U) +/** + * @} + */ + +/** @defgroup FSMC_ECC_Page_Size FSMC ECC Page Size + * @{ + */ +#define FSMC_NAND_ECC_PAGE_SIZE_256BYTE (0x00000000U) +#define FSMC_NAND_ECC_PAGE_SIZE_512BYTE (0x00020000U) +#define FSMC_NAND_ECC_PAGE_SIZE_1024BYTE (0x00040000U) +#define FSMC_NAND_ECC_PAGE_SIZE_2048BYTE (0x00060000U) +#define FSMC_NAND_ECC_PAGE_SIZE_4096BYTE (0x00080000U) +#define FSMC_NAND_ECC_PAGE_SIZE_8192BYTE (0x000A0000U) +/** + * @} + */ + +/** + * @} + */ +#endif /* FSMC_Bank2_3 || FSMC_Bank4 */ + + +/** @defgroup FSMC_LL_Interrupt_definition FSMC Low Layer Interrupt definition + * @{ + */ +#if defined(FSMC_Bank2_3) || defined(FSMC_Bank4) +#define FSMC_IT_RISING_EDGE (0x00000008U) +#define FSMC_IT_LEVEL (0x00000010U) +#define FSMC_IT_FALLING_EDGE (0x00000020U) +#endif /* FSMC_Bank2_3 || FSMC_Bank4 */ +/** + * @} + */ + +/** @defgroup FSMC_LL_Flag_definition FSMC Low Layer Flag definition + * @{ + */ +#if defined(FSMC_Bank2_3) || defined(FSMC_Bank4) +#define FSMC_FLAG_RISING_EDGE (0x00000001U) +#define FSMC_FLAG_LEVEL (0x00000002U) +#define FSMC_FLAG_FALLING_EDGE (0x00000004U) +#define FSMC_FLAG_FEMPT (0x00000040U) +#endif /* FSMC_Bank2_3 || FSMC_Bank4 */ +/** + * @} + */ + +/** @defgroup FSMC_LL_Alias_definition FSMC Alias definition + * @{ + */ +#define FMC_WRITE_OPERATION_DISABLE FSMC_WRITE_OPERATION_DISABLE +#define FMC_WRITE_OPERATION_ENABLE FSMC_WRITE_OPERATION_ENABLE + +#define FMC_NORSRAM_MEM_BUS_WIDTH_8 FSMC_NORSRAM_MEM_BUS_WIDTH_8 +#define FMC_NORSRAM_MEM_BUS_WIDTH_16 FSMC_NORSRAM_MEM_BUS_WIDTH_16 +#define FMC_NORSRAM_MEM_BUS_WIDTH_32 FSMC_NORSRAM_MEM_BUS_WIDTH_32 + +#define FMC_NORSRAM_TypeDef FSMC_NORSRAM_TypeDef +#define FMC_NORSRAM_EXTENDED_TypeDef FSMC_NORSRAM_EXTENDED_TypeDef +#define FMC_NORSRAM_InitTypeDef FSMC_NORSRAM_InitTypeDef +#define FMC_NORSRAM_TimingTypeDef FSMC_NORSRAM_TimingTypeDef + +#define FMC_NORSRAM_Init FSMC_NORSRAM_Init +#define FMC_NORSRAM_Timing_Init FSMC_NORSRAM_Timing_Init +#define FMC_NORSRAM_Extended_Timing_Init FSMC_NORSRAM_Extended_Timing_Init +#define FMC_NORSRAM_DeInit FSMC_NORSRAM_DeInit +#define FMC_NORSRAM_WriteOperation_Enable FSMC_NORSRAM_WriteOperation_Enable +#define FMC_NORSRAM_WriteOperation_Disable FSMC_NORSRAM_WriteOperation_Disable + +#define __FMC_NORSRAM_ENABLE __FSMC_NORSRAM_ENABLE +#define __FMC_NORSRAM_DISABLE __FSMC_NORSRAM_DISABLE + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) +#define FMC_NAND_InitTypeDef FSMC_NAND_InitTypeDef +#define FMC_PCCARD_InitTypeDef FSMC_PCCARD_InitTypeDef +#define FMC_NAND_PCC_TimingTypeDef FSMC_NAND_PCC_TimingTypeDef + +#define FMC_NAND_Init FSMC_NAND_Init +#define FMC_NAND_CommonSpace_Timing_Init FSMC_NAND_CommonSpace_Timing_Init +#define FMC_NAND_AttributeSpace_Timing_Init FSMC_NAND_AttributeSpace_Timing_Init +#define FMC_NAND_DeInit FSMC_NAND_DeInit +#define FMC_NAND_ECC_Enable FSMC_NAND_ECC_Enable +#define FMC_NAND_ECC_Disable FSMC_NAND_ECC_Disable +#define FMC_NAND_GetECC FSMC_NAND_GetECC +#define FMC_PCCARD_Init FSMC_PCCARD_Init +#define FMC_PCCARD_CommonSpace_Timing_Init FSMC_PCCARD_CommonSpace_Timing_Init +#define FMC_PCCARD_AttributeSpace_Timing_Init FSMC_PCCARD_AttributeSpace_Timing_Init +#define FMC_PCCARD_IOSpace_Timing_Init FSMC_PCCARD_IOSpace_Timing_Init +#define FMC_PCCARD_DeInit FSMC_PCCARD_DeInit + +#define __FMC_NAND_ENABLE __FSMC_NAND_ENABLE +#define __FMC_NAND_DISABLE __FSMC_NAND_DISABLE +#define __FMC_PCCARD_ENABLE __FSMC_PCCARD_ENABLE +#define __FMC_PCCARD_DISABLE __FSMC_PCCARD_DISABLE +#define __FMC_NAND_ENABLE_IT __FSMC_NAND_ENABLE_IT +#define __FMC_NAND_DISABLE_IT __FSMC_NAND_DISABLE_IT +#define __FMC_NAND_GET_FLAG __FSMC_NAND_GET_FLAG +#define __FMC_NAND_CLEAR_FLAG __FSMC_NAND_CLEAR_FLAG +#define __FMC_PCCARD_ENABLE_IT __FSMC_PCCARD_ENABLE_IT +#define __FMC_PCCARD_DISABLE_IT __FSMC_PCCARD_DISABLE_IT +#define __FMC_PCCARD_GET_FLAG __FSMC_PCCARD_GET_FLAG +#define __FMC_PCCARD_CLEAR_FLAG __FSMC_PCCARD_CLEAR_FLAG +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx */ + +#define FMC_NORSRAM_TypeDef FSMC_NORSRAM_TypeDef +#define FMC_NORSRAM_EXTENDED_TypeDef FSMC_NORSRAM_EXTENDED_TypeDef +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) +#define FMC_NAND_TypeDef FSMC_NAND_TypeDef +#define FMC_PCCARD_TypeDef FSMC_PCCARD_TypeDef +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx */ + +#define FMC_NORSRAM_DEVICE FSMC_NORSRAM_DEVICE +#define FMC_NORSRAM_EXTENDED_DEVICE FSMC_NORSRAM_EXTENDED_DEVICE +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) +#define FMC_NAND_DEVICE FSMC_NAND_DEVICE +#define FMC_PCCARD_DEVICE FSMC_PCCARD_DEVICE + +#define FMC_NAND_BANK2 FSMC_NAND_BANK2 +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx */ + +#define FMC_NORSRAM_BANK1 FSMC_NORSRAM_BANK1 +#define FMC_NORSRAM_BANK2 FSMC_NORSRAM_BANK2 +#define FMC_NORSRAM_BANK3 FSMC_NORSRAM_BANK3 + +#define FMC_IT_RISING_EDGE FSMC_IT_RISING_EDGE +#define FMC_IT_LEVEL FSMC_IT_LEVEL +#define FMC_IT_FALLING_EDGE FSMC_IT_FALLING_EDGE +#define FMC_IT_REFRESH_ERROR FSMC_IT_REFRESH_ERROR + +#define FMC_FLAG_RISING_EDGE FSMC_FLAG_RISING_EDGE +#define FMC_FLAG_LEVEL FSMC_FLAG_LEVEL +#define FMC_FLAG_FALLING_EDGE FSMC_FLAG_FALLING_EDGE +#define FMC_FLAG_FEMPT FSMC_FLAG_FEMPT +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/** @defgroup FSMC_LL_Private_Macros FSMC_LL Private Macros + * @{ + */ +#if defined(FSMC_Bank1) +/** @defgroup FSMC_LL_NOR_Macros FSMC NOR/SRAM Macros + * @brief macros to handle NOR device enable/disable and read/write operations + * @{ + */ + +/** + * @brief Enable the NORSRAM device access. + * @param __INSTANCE__ FSMC_NORSRAM Instance + * @param __BANK__ FSMC_NORSRAM Bank + * @retval None + */ +#define __FSMC_NORSRAM_ENABLE(__INSTANCE__, __BANK__) ((__INSTANCE__)->BTCR[(__BANK__)]\ + |= FSMC_BCR1_MBKEN) + +/** + * @brief Disable the NORSRAM device access. + * @param __INSTANCE__ FSMC_NORSRAM Instance + * @param __BANK__ FSMC_NORSRAM Bank + * @retval None + */ +#define __FSMC_NORSRAM_DISABLE(__INSTANCE__, __BANK__) ((__INSTANCE__)->BTCR[(__BANK__)]\ + &= ~FSMC_BCR1_MBKEN) + +/** + * @} + */ +#endif /* FSMC_Bank1 */ + +#if defined(FSMC_Bank2_3) +/** @defgroup FSMC_LL_NAND_Macros FSMC NAND Macros + * @brief macros to handle NAND device enable/disable + * @{ + */ + +/** + * @brief Enable the NAND device access. + * @param __INSTANCE__ FSMC_NAND Instance + * @param __BANK__ FSMC_NAND Bank + * @retval None + */ +#define __FSMC_NAND_ENABLE(__INSTANCE__, __BANK__) (((__BANK__) == FSMC_NAND_BANK2)? ((__INSTANCE__)->PCR2 |= FSMC_PCR2_PBKEN): \ + ((__INSTANCE__)->PCR3 |= FSMC_PCR3_PBKEN)) + +/** + * @brief Disable the NAND device access. + * @param __INSTANCE__ FSMC_NAND Instance + * @param __BANK__ FSMC_NAND Bank + * @retval None + */ +#define __FSMC_NAND_DISABLE(__INSTANCE__, __BANK__) (((__BANK__) == FSMC_NAND_BANK2)? CLEAR_BIT((__INSTANCE__)->PCR2, FSMC_PCR2_PBKEN): \ + CLEAR_BIT((__INSTANCE__)->PCR3, FSMC_PCR3_PBKEN)) + +/** + * @} + */ +#endif /* FSMC_Bank2_3 */ + +#if defined(FSMC_Bank4) +/** @defgroup FSMC_LL_PCCARD_Macros FMC PCCARD Macros + * @brief macros to handle PCCARD read/write operations + * @{ + */ +/** + * @brief Enable the PCCARD device access. + * @param __INSTANCE__ FSMC_PCCARD Instance + * @retval None + */ +#define __FSMC_PCCARD_ENABLE(__INSTANCE__) ((__INSTANCE__)->PCR4 |= FSMC_PCR4_PBKEN) + +/** + * @brief Disable the PCCARD device access. + * @param __INSTANCE__ FSMC_PCCARD Instance + * @retval None + */ +#define __FSMC_PCCARD_DISABLE(__INSTANCE__) ((__INSTANCE__)->PCR4 &= ~FSMC_PCR4_PBKEN) +/** + * @} + */ + +#endif +#if defined(FSMC_Bank2_3) +/** @defgroup FSMC_LL_NAND_Interrupt FSMC NAND Interrupt + * @brief macros to handle NAND interrupts + * @{ + */ + +/** + * @brief Enable the NAND device interrupt. + * @param __INSTANCE__ FSMC_NAND instance + * @param __BANK__ FSMC_NAND Bank + * @param __INTERRUPT__ FSMC_NAND interrupt + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FSMC_IT_LEVEL: Interrupt level. + * @arg FSMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FSMC_NAND_ENABLE_IT(__INSTANCE__, __BANK__, __INTERRUPT__) (((__BANK__) == FSMC_NAND_BANK2)? ((__INSTANCE__)->SR2 |= (__INTERRUPT__)): \ + ((__INSTANCE__)->SR3 |= (__INTERRUPT__))) + +/** + * @brief Disable the NAND device interrupt. + * @param __INSTANCE__ FSMC_NAND Instance + * @param __BANK__ FSMC_NAND Bank + * @param __INTERRUPT__ FSMC_NAND interrupt + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FSMC_IT_LEVEL: Interrupt level. + * @arg FSMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FSMC_NAND_DISABLE_IT(__INSTANCE__, __BANK__, __INTERRUPT__) (((__BANK__) == FSMC_NAND_BANK2)? ((__INSTANCE__)->SR2 &= ~(__INTERRUPT__)): \ + ((__INSTANCE__)->SR3 &= ~(__INTERRUPT__))) + +/** + * @brief Get flag status of the NAND device. + * @param __INSTANCE__ FSMC_NAND Instance + * @param __BANK__ FSMC_NAND Bank + * @param __FLAG__ FSMC_NAND flag + * This parameter can be any combination of the following values: + * @arg FSMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FSMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FSMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FSMC_FLAG_FEMPT: FIFO empty flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __FSMC_NAND_GET_FLAG(__INSTANCE__, __BANK__, __FLAG__) (((__BANK__) == FSMC_NAND_BANK2)? (((__INSTANCE__)->SR2 &(__FLAG__)) == (__FLAG__)): \ + (((__INSTANCE__)->SR3 &(__FLAG__)) == (__FLAG__))) + +/** + * @brief Clear flag status of the NAND device. + * @param __INSTANCE__ FSMC_NAND Instance + * @param __BANK__ FSMC_NAND Bank + * @param __FLAG__ FSMC_NAND flag + * This parameter can be any combination of the following values: + * @arg FSMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FSMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FSMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FSMC_FLAG_FEMPT: FIFO empty flag. + * @retval None + */ +#define __FSMC_NAND_CLEAR_FLAG(__INSTANCE__, __BANK__, __FLAG__) (((__BANK__) == FSMC_NAND_BANK2)? ((__INSTANCE__)->SR2 &= ~(__FLAG__)): \ + ((__INSTANCE__)->SR3 &= ~(__FLAG__))) + +/** + * @} + */ +#endif /* FSMC_Bank2_3 */ + +#if defined(FSMC_Bank4) +/** @defgroup FSMC_LL_PCCARD_Interrupt FSMC PCCARD Interrupt + * @brief macros to handle PCCARD interrupts + * @{ + */ + +/** + * @brief Enable the PCCARD device interrupt. + * @param __INSTANCE__ FSMC_PCCARD instance + * @param __INTERRUPT__ FSMC_PCCARD interrupt + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FSMC_IT_LEVEL: Interrupt level. + * @arg FSMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FSMC_PCCARD_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR4 |= (__INTERRUPT__)) + +/** + * @brief Disable the PCCARD device interrupt. + * @param __INSTANCE__ FSMC_PCCARD instance + * @param __INTERRUPT__ FSMC_PCCARD interrupt + * This parameter can be any combination of the following values: + * @arg FSMC_IT_RISING_EDGE: Interrupt rising edge. + * @arg FSMC_IT_LEVEL: Interrupt level. + * @arg FSMC_IT_FALLING_EDGE: Interrupt falling edge. + * @retval None + */ +#define __FSMC_PCCARD_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->SR4 &= ~(__INTERRUPT__)) + +/** + * @brief Get flag status of the PCCARD device. + * @param __INSTANCE__ FSMC_PCCARD instance + * @param __FLAG__ FSMC_PCCARD flag + * This parameter can be any combination of the following values: + * @arg FSMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FSMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FSMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FSMC_FLAG_FEMPT: FIFO empty flag. + * @retval The state of FLAG (SET or RESET). + */ +#define __FSMC_PCCARD_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->SR4 &(__FLAG__)) == (__FLAG__)) + +/** + * @brief Clear flag status of the PCCARD device. + * @param __INSTANCE__ FSMC_PCCARD instance + * @param __FLAG__ FSMC_PCCARD flag + * This parameter can be any combination of the following values: + * @arg FSMC_FLAG_RISING_EDGE: Interrupt rising edge flag. + * @arg FSMC_FLAG_LEVEL: Interrupt level edge flag. + * @arg FSMC_FLAG_FALLING_EDGE: Interrupt falling edge flag. + * @arg FSMC_FLAG_FEMPT: FIFO empty flag. + * @retval None + */ +#define __FSMC_PCCARD_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->SR4 &= ~(__FLAG__)) + +/** + * @} + */ +#endif + +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @defgroup FSMC_LL_Private_Functions FSMC LL Private Functions + * @{ + */ + +#if defined(FSMC_Bank1) +/** @defgroup FSMC_LL_NORSRAM NOR SRAM + * @{ + */ +/** @defgroup FSMC_LL_NORSRAM_Private_Functions_Group1 NOR SRAM Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FSMC_NORSRAM_Init(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_InitTypeDef *Init); +HAL_StatusTypeDef FSMC_NORSRAM_Timing_Init(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FSMC_NORSRAM_Extended_Timing_Init(FSMC_NORSRAM_EXTENDED_TypeDef *Device, + FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, + uint32_t ExtendedMode); +HAL_StatusTypeDef FSMC_NORSRAM_DeInit(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank); +/** + * @} + */ + +/** @defgroup FSMC_LL_NORSRAM_Private_Functions_Group2 NOR SRAM Control functions + * @{ + */ +HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Enable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Disable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank); +/** + * @} + */ +/** + * @} + */ +#endif /* FSMC_Bank1 */ + +#if defined(FSMC_Bank2_3) +/** @defgroup FSMC_LL_NAND NAND + * @{ + */ +/** @defgroup FSMC_LL_NAND_Private_Functions_Group1 NAND Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FSMC_NAND_Init(FSMC_NAND_TypeDef *Device, FSMC_NAND_InitTypeDef *Init); +HAL_StatusTypeDef FSMC_NAND_CommonSpace_Timing_Init(FSMC_NAND_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FSMC_NAND_AttributeSpace_Timing_Init(FSMC_NAND_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank); +HAL_StatusTypeDef FSMC_NAND_DeInit(FSMC_NAND_TypeDef *Device, uint32_t Bank); +/** + * @} + */ + +/** @defgroup FSMC_LL_NAND_Private_Functions_Group2 NAND Control functions + * @{ + */ +HAL_StatusTypeDef FSMC_NAND_ECC_Enable(FSMC_NAND_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FSMC_NAND_ECC_Disable(FSMC_NAND_TypeDef *Device, uint32_t Bank); +HAL_StatusTypeDef FSMC_NAND_GetECC(FSMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, + uint32_t Timeout); +/** + * @} + */ +/** + * @} + */ +#endif /* FSMC_Bank2_3 */ + +#if defined(FSMC_Bank4) +/** @defgroup FSMC_LL_PCCARD PCCARD + * @{ + */ +/** @defgroup FSMC_LL_PCCARD_Private_Functions_Group1 PCCARD Initialization/de-initialization functions + * @{ + */ +HAL_StatusTypeDef FSMC_PCCARD_Init(FSMC_PCCARD_TypeDef *Device, FSMC_PCCARD_InitTypeDef *Init); +HAL_StatusTypeDef FSMC_PCCARD_CommonSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FSMC_PCCARD_AttributeSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FSMC_PCCARD_IOSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing); +HAL_StatusTypeDef FSMC_PCCARD_DeInit(FSMC_PCCARD_TypeDef *Device); +/** + * @} + */ +/** + * @} + */ +#endif /* FSMC_Bank4 */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_FSMC_H */ diff --git a/libs/hal/stm32f4xx_ll_gpio.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h similarity index 100% rename from libs/hal/stm32f4xx_ll_gpio.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_gpio.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h new file mode 100644 index 0000000..babba6b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_i2c.h @@ -0,0 +1,1890 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_i2c.h + * @author MCD Application Team + * @brief Header file of I2C 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 __STM32F4xx_LL_I2C_H +#define __STM32F4xx_LL_I2C_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (I2C1) || defined (I2C2) || defined (I2C3) + +/** @defgroup I2C_LL I2C + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2C_LL_Private_Constants I2C Private Constants + * @{ + */ + +/* Defines used to perform compute and check in the macros */ +#define LL_I2C_MAX_SPEED_STANDARD 100000U +#define LL_I2C_MAX_SPEED_FAST 400000U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2C_LL_Private_Macros I2C Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2C_LL_ES_INIT I2C Exported Init structure + * @{ + */ +typedef struct +{ + uint32_t PeripheralMode; /*!< Specifies the peripheral mode. + This parameter can be a value of @ref I2C_LL_EC_PERIPHERAL_MODE + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetMode(). */ + + uint32_t ClockSpeed; /*!< Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz (in Hz) + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetClockPeriod() + or @ref LL_I2C_SetDutyCycle() or @ref LL_I2C_SetClockSpeedMode() or @ref LL_I2C_ConfigSpeed(). */ + + uint32_t DutyCycle; /*!< Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_LL_EC_DUTYCYCLE + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetDutyCycle(). */ + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) + uint32_t AnalogFilter; /*!< Enables or disables analog noise filter. + This parameter can be a value of @ref I2C_LL_EC_ANALOGFILTER_SELECTION + + This feature can be modified afterwards using unitary functions @ref LL_I2C_EnableAnalogFilter() or LL_I2C_DisableAnalogFilter(). */ + + uint32_t DigitalFilter; /*!< Configures the digital noise filter. + This parameter can be a number between Min_Data = 0x00 and Max_Data = 0x0F + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetDigitalFilter(). */ + +#endif + uint32_t OwnAddress1; /*!< Specifies the device own address 1. + This parameter must be a value between Min_Data = 0x00 and Max_Data = 0x3FF + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetOwnAddress1(). */ + + uint32_t TypeAcknowledge; /*!< Specifies the ACKnowledge or Non ACKnowledge condition after the address receive match code or next received byte. + This parameter can be a value of @ref I2C_LL_EC_I2C_ACKNOWLEDGE + + This feature can be modified afterwards using unitary function @ref LL_I2C_AcknowledgeNextData(). */ + + uint32_t OwnAddrSize; /*!< Specifies the device own address 1 size (7-bit or 10-bit). + This parameter can be a value of @ref I2C_LL_EC_OWNADDRESS1 + + This feature can be modified afterwards using unitary function @ref LL_I2C_SetOwnAddress1(). */ +} LL_I2C_InitTypeDef; +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2C_LL_Exported_Constants I2C Exported Constants + * @{ + */ + +/** @defgroup I2C_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_I2C_ReadReg function + * @{ + */ +#define LL_I2C_SR1_SB I2C_SR1_SB /*!< Start Bit (master mode) */ +#define LL_I2C_SR1_ADDR I2C_SR1_ADDR /*!< Address sent (master mode) or + Address matched flag (slave mode) */ +#define LL_I2C_SR1_BTF I2C_SR1_BTF /*!< Byte Transfer Finished flag */ +#define LL_I2C_SR1_ADD10 I2C_SR1_ADD10 /*!< 10-bit header sent (master mode) */ +#define LL_I2C_SR1_STOPF I2C_SR1_STOPF /*!< Stop detection flag (slave mode) */ +#define LL_I2C_SR1_RXNE I2C_SR1_RXNE /*!< Data register not empty (receivers) */ +#define LL_I2C_SR1_TXE I2C_SR1_TXE /*!< Data register empty (transmitters) */ +#define LL_I2C_SR1_BERR I2C_SR1_BERR /*!< Bus error */ +#define LL_I2C_SR1_ARLO I2C_SR1_ARLO /*!< Arbitration lost */ +#define LL_I2C_SR1_AF I2C_SR1_AF /*!< Acknowledge failure flag */ +#define LL_I2C_SR1_OVR I2C_SR1_OVR /*!< Overrun/Underrun */ +#define LL_I2C_SR1_PECERR I2C_ISR_PECERR /*!< PEC Error in reception (SMBus mode) */ +#define LL_I2C_SR1_TIMEOUT I2C_ISR_TIMEOUT /*!< Timeout detection flag (SMBus mode) */ +#define LL_I2C_SR1_SMALERT I2C_ISR_SMALERT /*!< SMBus alert (SMBus mode) */ +#define LL_I2C_SR2_MSL I2C_SR2_MSL /*!< Master/Slave flag */ +#define LL_I2C_SR2_BUSY I2C_SR2_BUSY /*!< Bus busy flag */ +#define LL_I2C_SR2_TRA I2C_SR2_TRA /*!< Transmitter/receiver direction */ +#define LL_I2C_SR2_GENCALL I2C_SR2_GENCALL /*!< General call address (Slave mode) */ +#define LL_I2C_SR2_SMBDEFAULT I2C_SR2_SMBDEFAULT /*!< SMBus Device default address (Slave mode) */ +#define LL_I2C_SR2_SMBHOST I2C_SR2_SMBHOST /*!< SMBus Host address (Slave mode) */ +#define LL_I2C_SR2_DUALF I2C_SR2_DUALF /*!< Dual flag (Slave mode) */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_I2C_ReadReg and LL_I2C_WriteReg functions + * @{ + */ +#define LL_I2C_CR2_ITEVTEN I2C_CR2_ITEVTEN /*!< Events interrupts enable */ +#define LL_I2C_CR2_ITBUFEN I2C_CR2_ITBUFEN /*!< Buffer interrupts enable */ +#define LL_I2C_CR2_ITERREN I2C_CR2_ITERREN /*!< Error interrupts enable */ +/** + * @} + */ + +#if defined(I2C_FLTR_ANOFF) +/** @defgroup I2C_LL_EC_ANALOGFILTER_SELECTION Analog Filter Selection + * @{ + */ +#define LL_I2C_ANALOGFILTER_ENABLE 0x00000000U /*!< Analog filter is enabled. */ +#define LL_I2C_ANALOGFILTER_DISABLE I2C_FLTR_ANOFF /*!< Analog filter is disabled.*/ +/** + * @} + */ + +#endif +/** @defgroup I2C_LL_EC_OWNADDRESS1 Own Address 1 Length + * @{ + */ +#define LL_I2C_OWNADDRESS1_7BIT 0x00004000U /*!< Own address 1 is a 7-bit address. */ +#define LL_I2C_OWNADDRESS1_10BIT (uint32_t)(I2C_OAR1_ADDMODE | 0x00004000U) /*!< Own address 1 is a 10-bit address. */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_DUTYCYCLE Fast Mode Duty Cycle + * @{ + */ +#define LL_I2C_DUTYCYCLE_2 0x00000000U /*!< I2C fast mode Tlow/Thigh = 2 */ +#define LL_I2C_DUTYCYCLE_16_9 I2C_CCR_DUTY /*!< I2C fast mode Tlow/Thigh = 16/9 */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_CLOCK_SPEED_MODE Master Clock Speed Mode + * @{ + */ +#define LL_I2C_CLOCK_SPEED_STANDARD_MODE 0x00000000U /*!< Master clock speed range is standard mode */ +#define LL_I2C_CLOCK_SPEED_FAST_MODE I2C_CCR_FS /*!< Master clock speed range is fast mode */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_PERIPHERAL_MODE Peripheral Mode + * @{ + */ +#define LL_I2C_MODE_I2C 0x00000000U /*!< I2C Master or Slave mode */ +#define LL_I2C_MODE_SMBUS_HOST (uint32_t)(I2C_CR1_SMBUS | I2C_CR1_SMBTYPE | I2C_CR1_ENARP) /*!< SMBus Host address acknowledge */ +#define LL_I2C_MODE_SMBUS_DEVICE I2C_CR1_SMBUS /*!< SMBus Device default mode (Default address not acknowledge) */ +#define LL_I2C_MODE_SMBUS_DEVICE_ARP (uint32_t)(I2C_CR1_SMBUS | I2C_CR1_ENARP) /*!< SMBus Device Default address acknowledge */ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_I2C_ACKNOWLEDGE Acknowledge Generation + * @{ + */ +#define LL_I2C_ACK I2C_CR1_ACK /*!< ACK is sent after current received byte. */ +#define LL_I2C_NACK 0x00000000U /*!< NACK is sent after current received byte.*/ +/** + * @} + */ + +/** @defgroup I2C_LL_EC_DIRECTION Read Write Direction + * @{ + */ +#define LL_I2C_DIRECTION_WRITE I2C_SR2_TRA /*!< Bus is in write transfer */ +#define LL_I2C_DIRECTION_READ 0x00000000U /*!< Bus is in read transfer */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup I2C_LL_Exported_Macros I2C Exported Macros + * @{ + */ + +/** @defgroup I2C_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in I2C register + * @param __INSTANCE__ I2C Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_I2C_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in I2C register + * @param __INSTANCE__ I2C Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_I2C_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup I2C_LL_EM_Exported_Macros_Helper Exported_Macros_Helper + * @{ + */ + +/** + * @brief Convert Peripheral Clock Frequency in Mhz. + * @param __PCLK__ This parameter must be a value of peripheral clock (in Hz). + * @retval Value of peripheral clock (in Mhz) + */ +#define __LL_I2C_FREQ_HZ_TO_MHZ(__PCLK__) (uint32_t)((__PCLK__)/1000000U) + +/** + * @brief Convert Peripheral Clock Frequency in Hz. + * @param __PCLK__ This parameter must be a value of peripheral clock (in Mhz). + * @retval Value of peripheral clock (in Hz) + */ +#define __LL_I2C_FREQ_MHZ_TO_HZ(__PCLK__) (uint32_t)((__PCLK__)*1000000U) + +/** + * @brief Compute I2C Clock rising time. + * @param __FREQRANGE__ This parameter must be a value of peripheral clock (in Mhz). + * @param __SPEED__ This parameter must be a value lower than 400kHz (in Hz). + * @retval Value between Min_Data=0x02 and Max_Data=0x3F + */ +#define __LL_I2C_RISE_TIME(__FREQRANGE__, __SPEED__) (uint32_t)(((__SPEED__) <= LL_I2C_MAX_SPEED_STANDARD) ? ((__FREQRANGE__) + 1U) : ((((__FREQRANGE__) * 300U) / 1000U) + 1U)) + +/** + * @brief Compute Speed clock range to a Clock Control Register (I2C_CCR_CCR) value. + * @param __PCLK__ This parameter must be a value of peripheral clock (in Hz). + * @param __SPEED__ This parameter must be a value lower than 400kHz (in Hz). + * @param __DUTYCYCLE__ This parameter can be one of the following values: + * @arg @ref LL_I2C_DUTYCYCLE_2 + * @arg @ref LL_I2C_DUTYCYCLE_16_9 + * @retval Value between Min_Data=0x004 and Max_Data=0xFFF, except in FAST DUTY mode where Min_Data=0x001. + */ +#define __LL_I2C_SPEED_TO_CCR(__PCLK__, __SPEED__, __DUTYCYCLE__) (uint32_t)(((__SPEED__) <= LL_I2C_MAX_SPEED_STANDARD)? \ + (__LL_I2C_SPEED_STANDARD_TO_CCR((__PCLK__), (__SPEED__))) : \ + (__LL_I2C_SPEED_FAST_TO_CCR((__PCLK__), (__SPEED__), (__DUTYCYCLE__)))) + +/** + * @brief Compute Speed Standard clock range to a Clock Control Register (I2C_CCR_CCR) value. + * @param __PCLK__ This parameter must be a value of peripheral clock (in Hz). + * @param __SPEED__ This parameter must be a value lower than 100kHz (in Hz). + * @retval Value between Min_Data=0x004 and Max_Data=0xFFF. + */ +#define __LL_I2C_SPEED_STANDARD_TO_CCR(__PCLK__, __SPEED__) (uint32_t)(((((__PCLK__)/((__SPEED__) << 1U)) & I2C_CCR_CCR) < 4U)? 4U:((__PCLK__) / ((__SPEED__) << 1U))) + +/** + * @brief Compute Speed Fast clock range to a Clock Control Register (I2C_CCR_CCR) value. + * @param __PCLK__ This parameter must be a value of peripheral clock (in Hz). + * @param __SPEED__ This parameter must be a value between Min_Data=100Khz and Max_Data=400Khz (in Hz). + * @param __DUTYCYCLE__ This parameter can be one of the following values: + * @arg @ref LL_I2C_DUTYCYCLE_2 + * @arg @ref LL_I2C_DUTYCYCLE_16_9 + * @retval Value between Min_Data=0x001 and Max_Data=0xFFF + */ +#define __LL_I2C_SPEED_FAST_TO_CCR(__PCLK__, __SPEED__, __DUTYCYCLE__) (uint32_t)(((__DUTYCYCLE__) == LL_I2C_DUTYCYCLE_2)? \ + (((((__PCLK__) / ((__SPEED__) * 3U)) & I2C_CCR_CCR) == 0U)? 1U:((__PCLK__) / ((__SPEED__) * 3U))) : \ + (((((__PCLK__) / ((__SPEED__) * 25U)) & I2C_CCR_CCR) == 0U)? 1U:((__PCLK__) / ((__SPEED__) * 25U)))) + +/** + * @brief Get the Least significant bits of a 10-Bits address. + * @param __ADDRESS__ This parameter must be a value of a 10-Bits slave address. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +#define __LL_I2C_10BIT_ADDRESS(__ADDRESS__) ((uint8_t)((uint16_t)((__ADDRESS__) & (uint16_t)(0x00FF)))) + +/** + * @brief Convert a 10-Bits address to a 10-Bits header with Write direction. + * @param __ADDRESS__ This parameter must be a value of a 10-Bits slave address. + * @retval Value between Min_Data=0xF0 and Max_Data=0xF6 + */ +#define __LL_I2C_10BIT_HEADER_WRITE(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF0)))) + +/** + * @brief Convert a 10-Bits address to a 10-Bits header with Read direction. + * @param __ADDRESS__ This parameter must be a value of a 10-Bits slave address. + * @retval Value between Min_Data=0xF1 and Max_Data=0xF7 + */ +#define __LL_I2C_10BIT_HEADER_READ(__ADDRESS__) ((uint8_t)((uint16_t)((uint16_t)(((uint16_t)((__ADDRESS__) & (uint16_t)(0x0300))) >> 7) | (uint16_t)(0xF1)))) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2C_LL_Exported_Functions I2C Exported Functions + * @{ + */ + +/** @defgroup I2C_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable I2C peripheral (PE = 1). + * @rmtoll CR1 PE LL_I2C_Enable + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_Enable(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_PE); +} + +/** + * @brief Disable I2C peripheral (PE = 0). + * @rmtoll CR1 PE LL_I2C_Disable + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_Disable(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_PE); +} + +/** + * @brief Check if the I2C peripheral is enabled or disabled. + * @rmtoll CR1 PE LL_I2C_IsEnabled + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabled(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_PE) == (I2C_CR1_PE)); +} + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +/** + * @brief Configure Noise Filters (Analog and Digital). + * @note If the analog filter is also enabled, the digital filter is added to analog filter. + * The filters can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll FLTR ANOFF LL_I2C_ConfigFilters\n + * FLTR DNF LL_I2C_ConfigFilters + * @param I2Cx I2C Instance. + * @param AnalogFilter This parameter can be one of the following values: + * @arg @ref LL_I2C_ANALOGFILTER_ENABLE + * @arg @ref LL_I2C_ANALOGFILTER_DISABLE + * @param DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled) and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*TPCLK1) + * This parameter is used to configure the digital noise filter on SDA and SCL input. The digital filter will suppress the spikes with a length of up to DNF[3:0]*TPCLK1. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ConfigFilters(I2C_TypeDef *I2Cx, uint32_t AnalogFilter, uint32_t DigitalFilter) +{ + MODIFY_REG(I2Cx->FLTR, I2C_FLTR_ANOFF | I2C_FLTR_DNF, AnalogFilter | DigitalFilter); +} +#endif +#if defined(I2C_FLTR_DNF) + +/** + * @brief Configure Digital Noise Filter. + * @note If the analog filter is also enabled, the digital filter is added to analog filter. + * This filter can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll FLTR DNF LL_I2C_SetDigitalFilter + * @param I2Cx I2C Instance. + * @param DigitalFilter This parameter must be a value between Min_Data=0x00 (Digital filter disabled) and Max_Data=0x0F (Digital filter enabled and filtering capability up to 15*TPCLK1) + * This parameter is used to configure the digital noise filter on SDA and SCL input. The digital filter will suppress the spikes with a length of up to DNF[3:0]*TPCLK1. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetDigitalFilter(I2C_TypeDef *I2Cx, uint32_t DigitalFilter) +{ + MODIFY_REG(I2Cx->FLTR, I2C_FLTR_DNF, DigitalFilter); +} + +/** + * @brief Get the current Digital Noise Filter configuration. + * @rmtoll FLTR DNF LL_I2C_GetDigitalFilter + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_I2C_GetDigitalFilter(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->FLTR, I2C_FLTR_DNF)); +} +#endif +#if defined(I2C_FLTR_ANOFF) + +/** + * @brief Enable Analog Noise Filter. + * @note This filter can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll FLTR ANOFF LL_I2C_EnableAnalogFilter + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableAnalogFilter(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->FLTR, I2C_FLTR_ANOFF); +} + +/** + * @brief Disable Analog Noise Filter. + * @note This filter can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll FLTR ANOFF LL_I2C_DisableAnalogFilter + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableAnalogFilter(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->FLTR, I2C_FLTR_ANOFF); +} + +/** + * @brief Check if Analog Noise Filter is enabled or disabled. + * @rmtoll FLTR ANOFF LL_I2C_IsEnabledAnalogFilter + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledAnalogFilter(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->FLTR, I2C_FLTR_ANOFF) == (I2C_FLTR_ANOFF)); +} +#endif + +/** + * @brief Enable DMA transmission requests. + * @rmtoll CR2 DMAEN LL_I2C_EnableDMAReq_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableDMAReq_TX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_DMAEN); +} + +/** + * @brief Disable DMA transmission requests. + * @rmtoll CR2 DMAEN LL_I2C_DisableDMAReq_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableDMAReq_TX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_DMAEN); +} + +/** + * @brief Check if DMA transmission requests are enabled or disabled. + * @rmtoll CR2 DMAEN LL_I2C_IsEnabledDMAReq_TX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_TX(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_DMAEN) == (I2C_CR2_DMAEN)); +} + +/** + * @brief Enable DMA reception requests. + * @rmtoll CR2 DMAEN LL_I2C_EnableDMAReq_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableDMAReq_RX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_DMAEN); +} + +/** + * @brief Disable DMA reception requests. + * @rmtoll CR2 DMAEN LL_I2C_DisableDMAReq_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableDMAReq_RX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_DMAEN); +} + +/** + * @brief Check if DMA reception requests are enabled or disabled. + * @rmtoll CR2 DMAEN LL_I2C_IsEnabledDMAReq_RX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledDMAReq_RX(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_DMAEN) == (I2C_CR2_DMAEN)); +} + +/** + * @brief Get the data register address used for DMA transfer. + * @rmtoll DR DR LL_I2C_DMA_GetRegAddr + * @param I2Cx I2C Instance. + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_I2C_DMA_GetRegAddr(I2C_TypeDef *I2Cx) +{ + return (uint32_t) & (I2Cx->DR); +} + +/** + * @brief Enable Clock stretching. + * @note This bit can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CR1 NOSTRETCH LL_I2C_EnableClockStretching + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableClockStretching(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH); +} + +/** + * @brief Disable Clock stretching. + * @note This bit can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CR1 NOSTRETCH LL_I2C_DisableClockStretching + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableClockStretching(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH); +} + +/** + * @brief Check if Clock stretching is enabled or disabled. + * @rmtoll CR1 NOSTRETCH LL_I2C_IsEnabledClockStretching + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledClockStretching(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_NOSTRETCH) != (I2C_CR1_NOSTRETCH)); +} + +/** + * @brief Enable General Call. + * @note When enabled the Address 0x00 is ACKed. + * @rmtoll CR1 ENGC LL_I2C_EnableGeneralCall + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableGeneralCall(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ENGC); +} + +/** + * @brief Disable General Call. + * @note When disabled the Address 0x00 is NACKed. + * @rmtoll CR1 ENGC LL_I2C_DisableGeneralCall + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableGeneralCall(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ENGC); +} + +/** + * @brief Check if General Call is enabled or disabled. + * @rmtoll CR1 ENGC LL_I2C_IsEnabledGeneralCall + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledGeneralCall(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_ENGC) == (I2C_CR1_ENGC)); +} + +/** + * @brief Set the Own Address1. + * @rmtoll OAR1 ADD0 LL_I2C_SetOwnAddress1\n + * OAR1 ADD1_7 LL_I2C_SetOwnAddress1\n + * OAR1 ADD8_9 LL_I2C_SetOwnAddress1\n + * OAR1 ADDMODE LL_I2C_SetOwnAddress1 + * @param I2Cx I2C Instance. + * @param OwnAddress1 This parameter must be a value between Min_Data=0 and Max_Data=0x3FF. + * @param OwnAddrSize This parameter can be one of the following values: + * @arg @ref LL_I2C_OWNADDRESS1_7BIT + * @arg @ref LL_I2C_OWNADDRESS1_10BIT + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetOwnAddress1(I2C_TypeDef *I2Cx, uint32_t OwnAddress1, uint32_t OwnAddrSize) +{ + MODIFY_REG(I2Cx->OAR1, I2C_OAR1_ADD0 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD8_9 | I2C_OAR1_ADDMODE, OwnAddress1 | OwnAddrSize); +} + +/** + * @brief Set the 7bits Own Address2. + * @note This action has no effect if own address2 is enabled. + * @rmtoll OAR2 ADD2 LL_I2C_SetOwnAddress2 + * @param I2Cx I2C Instance. + * @param OwnAddress2 This parameter must be a value between Min_Data=0 and Max_Data=0x7F. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetOwnAddress2(I2C_TypeDef *I2Cx, uint32_t OwnAddress2) +{ + MODIFY_REG(I2Cx->OAR2, I2C_OAR2_ADD2, OwnAddress2); +} + +/** + * @brief Enable acknowledge on Own Address2 match address. + * @rmtoll OAR2 ENDUAL LL_I2C_EnableOwnAddress2 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableOwnAddress2(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->OAR2, I2C_OAR2_ENDUAL); +} + +/** + * @brief Disable acknowledge on Own Address2 match address. + * @rmtoll OAR2 ENDUAL LL_I2C_DisableOwnAddress2 + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableOwnAddress2(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->OAR2, I2C_OAR2_ENDUAL); +} + +/** + * @brief Check if Own Address1 acknowledge is enabled or disabled. + * @rmtoll OAR2 ENDUAL LL_I2C_IsEnabledOwnAddress2 + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledOwnAddress2(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->OAR2, I2C_OAR2_ENDUAL) == (I2C_OAR2_ENDUAL)); +} + +/** + * @brief Configure the Peripheral clock frequency. + * @rmtoll CR2 FREQ LL_I2C_SetPeriphClock + * @param I2Cx I2C Instance. + * @param PeriphClock Peripheral Clock (in Hz) + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetPeriphClock(I2C_TypeDef *I2Cx, uint32_t PeriphClock) +{ + MODIFY_REG(I2Cx->CR2, I2C_CR2_FREQ, __LL_I2C_FREQ_HZ_TO_MHZ(PeriphClock)); +} + +/** + * @brief Get the Peripheral clock frequency. + * @rmtoll CR2 FREQ LL_I2C_GetPeriphClock + * @param I2Cx I2C Instance. + * @retval Value of Peripheral Clock (in Hz) + */ +__STATIC_INLINE uint32_t LL_I2C_GetPeriphClock(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(__LL_I2C_FREQ_MHZ_TO_HZ(READ_BIT(I2Cx->CR2, I2C_CR2_FREQ))); +} + +/** + * @brief Configure the Duty cycle (Fast mode only). + * @rmtoll CCR DUTY LL_I2C_SetDutyCycle + * @param I2Cx I2C Instance. + * @param DutyCycle This parameter can be one of the following values: + * @arg @ref LL_I2C_DUTYCYCLE_2 + * @arg @ref LL_I2C_DUTYCYCLE_16_9 + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetDutyCycle(I2C_TypeDef *I2Cx, uint32_t DutyCycle) +{ + MODIFY_REG(I2Cx->CCR, I2C_CCR_DUTY, DutyCycle); +} + +/** + * @brief Get the Duty cycle (Fast mode only). + * @rmtoll CCR DUTY LL_I2C_GetDutyCycle + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_DUTYCYCLE_2 + * @arg @ref LL_I2C_DUTYCYCLE_16_9 + */ +__STATIC_INLINE uint32_t LL_I2C_GetDutyCycle(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CCR, I2C_CCR_DUTY)); +} + +/** + * @brief Configure the I2C master clock speed mode. + * @rmtoll CCR FS LL_I2C_SetClockSpeedMode + * @param I2Cx I2C Instance. + * @param ClockSpeedMode This parameter can be one of the following values: + * @arg @ref LL_I2C_CLOCK_SPEED_STANDARD_MODE + * @arg @ref LL_I2C_CLOCK_SPEED_FAST_MODE + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetClockSpeedMode(I2C_TypeDef *I2Cx, uint32_t ClockSpeedMode) +{ + MODIFY_REG(I2Cx->CCR, I2C_CCR_FS, ClockSpeedMode); +} + +/** + * @brief Get the the I2C master speed mode. + * @rmtoll CCR FS LL_I2C_GetClockSpeedMode + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_CLOCK_SPEED_STANDARD_MODE + * @arg @ref LL_I2C_CLOCK_SPEED_FAST_MODE + */ +__STATIC_INLINE uint32_t LL_I2C_GetClockSpeedMode(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CCR, I2C_CCR_FS)); +} + +/** + * @brief Configure the SCL, SDA rising time. + * @note This bit can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll TRISE TRISE LL_I2C_SetRiseTime + * @param I2Cx I2C Instance. + * @param RiseTime This parameter must be a value between Min_Data=0x02 and Max_Data=0x3F. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetRiseTime(I2C_TypeDef *I2Cx, uint32_t RiseTime) +{ + MODIFY_REG(I2Cx->TRISE, I2C_TRISE_TRISE, RiseTime); +} + +/** + * @brief Get the SCL, SDA rising time. + * @rmtoll TRISE TRISE LL_I2C_GetRiseTime + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x02 and Max_Data=0x3F + */ +__STATIC_INLINE uint32_t LL_I2C_GetRiseTime(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->TRISE, I2C_TRISE_TRISE)); +} + +/** + * @brief Configure the SCL high and low period. + * @note This bit can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CCR CCR LL_I2C_SetClockPeriod + * @param I2Cx I2C Instance. + * @param ClockPeriod This parameter must be a value between Min_Data=0x004 and Max_Data=0xFFF, except in FAST DUTY mode where Min_Data=0x001. + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetClockPeriod(I2C_TypeDef *I2Cx, uint32_t ClockPeriod) +{ + MODIFY_REG(I2Cx->CCR, I2C_CCR_CCR, ClockPeriod); +} + +/** + * @brief Get the SCL high and low period. + * @rmtoll CCR CCR LL_I2C_GetClockPeriod + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x004 and Max_Data=0xFFF, except in FAST DUTY mode where Min_Data=0x001. + */ +__STATIC_INLINE uint32_t LL_I2C_GetClockPeriod(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CCR, I2C_CCR_CCR)); +} + +/** + * @brief Configure the SCL speed. + * @note This bit can only be programmed when the I2C is disabled (PE = 0). + * @rmtoll CR2 FREQ LL_I2C_ConfigSpeed\n + * TRISE TRISE LL_I2C_ConfigSpeed\n + * CCR FS LL_I2C_ConfigSpeed\n + * CCR DUTY LL_I2C_ConfigSpeed\n + * CCR CCR LL_I2C_ConfigSpeed + * @param I2Cx I2C Instance. + * @param PeriphClock Peripheral Clock (in Hz) + * @param ClockSpeed This parameter must be a value lower than 400kHz (in Hz). + * @param DutyCycle This parameter can be one of the following values: + * @arg @ref LL_I2C_DUTYCYCLE_2 + * @arg @ref LL_I2C_DUTYCYCLE_16_9 + * @retval None + */ +__STATIC_INLINE void LL_I2C_ConfigSpeed(I2C_TypeDef *I2Cx, uint32_t PeriphClock, uint32_t ClockSpeed, + uint32_t DutyCycle) +{ + uint32_t freqrange = 0x0U; + uint32_t clockconfig = 0x0U; + + /* Compute frequency range */ + freqrange = __LL_I2C_FREQ_HZ_TO_MHZ(PeriphClock); + + /* Configure I2Cx: Frequency range register */ + MODIFY_REG(I2Cx->CR2, I2C_CR2_FREQ, freqrange); + + /* Configure I2Cx: Rise Time register */ + MODIFY_REG(I2Cx->TRISE, I2C_TRISE_TRISE, __LL_I2C_RISE_TIME(freqrange, ClockSpeed)); + + /* Configure Speed mode, Duty Cycle and Clock control register value */ + if (ClockSpeed > LL_I2C_MAX_SPEED_STANDARD) + { + /* Set Speed mode at fast and duty cycle for Clock Speed request in fast clock range */ + clockconfig = LL_I2C_CLOCK_SPEED_FAST_MODE | \ + __LL_I2C_SPEED_FAST_TO_CCR(PeriphClock, ClockSpeed, DutyCycle) | \ + DutyCycle; + } + else + { + /* Set Speed mode at standard for Clock Speed request in standard clock range */ + clockconfig = LL_I2C_CLOCK_SPEED_STANDARD_MODE | \ + __LL_I2C_SPEED_STANDARD_TO_CCR(PeriphClock, ClockSpeed); + } + + /* Configure I2Cx: Clock control register */ + MODIFY_REG(I2Cx->CCR, (I2C_CCR_FS | I2C_CCR_DUTY | I2C_CCR_CCR), clockconfig); +} + +/** + * @brief Configure peripheral mode. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 SMBUS LL_I2C_SetMode\n + * CR1 SMBTYPE LL_I2C_SetMode\n + * CR1 ENARP LL_I2C_SetMode + * @param I2Cx I2C Instance. + * @param PeripheralMode This parameter can be one of the following values: + * @arg @ref LL_I2C_MODE_I2C + * @arg @ref LL_I2C_MODE_SMBUS_HOST + * @arg @ref LL_I2C_MODE_SMBUS_DEVICE + * @arg @ref LL_I2C_MODE_SMBUS_DEVICE_ARP + * @retval None + */ +__STATIC_INLINE void LL_I2C_SetMode(I2C_TypeDef *I2Cx, uint32_t PeripheralMode) +{ + MODIFY_REG(I2Cx->CR1, I2C_CR1_SMBUS | I2C_CR1_SMBTYPE | I2C_CR1_ENARP, PeripheralMode); +} + +/** + * @brief Get peripheral mode. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 SMBUS LL_I2C_GetMode\n + * CR1 SMBTYPE LL_I2C_GetMode\n + * CR1 ENARP LL_I2C_GetMode + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_MODE_I2C + * @arg @ref LL_I2C_MODE_SMBUS_HOST + * @arg @ref LL_I2C_MODE_SMBUS_DEVICE + * @arg @ref LL_I2C_MODE_SMBUS_DEVICE_ARP + */ +__STATIC_INLINE uint32_t LL_I2C_GetMode(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->CR1, I2C_CR1_SMBUS | I2C_CR1_SMBTYPE | I2C_CR1_ENARP)); +} + +/** + * @brief Enable SMBus alert (Host or Device mode) + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note SMBus Device mode: + * - SMBus Alert pin is drived low and + * Alert Response Address Header acknowledge is enabled. + * SMBus Host mode: + * - SMBus Alert pin management is supported. + * @rmtoll CR1 ALERT LL_I2C_EnableSMBusAlert + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusAlert(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ALERT); +} + +/** + * @brief Disable SMBus alert (Host or Device mode) + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note SMBus Device mode: + * - SMBus Alert pin is not drived (can be used as a standard GPIO) and + * Alert Response Address Header acknowledge is disabled. + * SMBus Host mode: + * - SMBus Alert pin management is not supported. + * @rmtoll CR1 ALERT LL_I2C_DisableSMBusAlert + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusAlert(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ALERT); +} + +/** + * @brief Check if SMBus alert (Host or Device mode) is enabled or disabled. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 ALERT LL_I2C_IsEnabledSMBusAlert + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusAlert(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_ALERT) == (I2C_CR1_ALERT)); +} + +/** + * @brief Enable SMBus Packet Error Calculation (PEC). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 ENPEC LL_I2C_EnableSMBusPEC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusPEC(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_ENPEC); +} + +/** + * @brief Disable SMBus Packet Error Calculation (PEC). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 ENPEC LL_I2C_DisableSMBusPEC + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusPEC(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_ENPEC); +} + +/** + * @brief Check if SMBus Packet Error Calculation (PEC) is enabled or disabled. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 ENPEC LL_I2C_IsEnabledSMBusPEC + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPEC(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_ENPEC) == (I2C_CR1_ENPEC)); +} + +/** + * @} + */ + +/** @defgroup I2C_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable TXE interrupt. + * @rmtoll CR2 ITEVTEN LL_I2C_EnableIT_TX\n + * CR2 ITBUFEN LL_I2C_EnableIT_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_TX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); +} + +/** + * @brief Disable TXE interrupt. + * @rmtoll CR2 ITEVTEN LL_I2C_DisableIT_TX\n + * CR2 ITBUFEN LL_I2C_DisableIT_TX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_TX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); +} + +/** + * @brief Check if the TXE Interrupt is enabled or disabled. + * @rmtoll CR2 ITEVTEN LL_I2C_IsEnabledIT_TX\n + * CR2 ITBUFEN LL_I2C_IsEnabledIT_TX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_TX(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN) == (I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN)); +} + +/** + * @brief Enable RXNE interrupt. + * @rmtoll CR2 ITEVTEN LL_I2C_EnableIT_RX\n + * CR2 ITBUFEN LL_I2C_EnableIT_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_RX(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); +} + +/** + * @brief Disable RXNE interrupt. + * @rmtoll CR2 ITEVTEN LL_I2C_DisableIT_RX\n + * CR2 ITBUFEN LL_I2C_DisableIT_RX + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_RX(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN); +} + +/** + * @brief Check if the RXNE Interrupt is enabled or disabled. + * @rmtoll CR2 ITEVTEN LL_I2C_IsEnabledIT_RX\n + * CR2 ITBUFEN LL_I2C_IsEnabledIT_RX + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_RX(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN) == (I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN)); +} + +/** + * @brief Enable Events interrupts. + * @note Any of these events will generate interrupt : + * Start Bit (SB) + * Address sent, Address matched (ADDR) + * 10-bit header sent (ADD10) + * Stop detection (STOPF) + * Byte transfer finished (BTF) + * + * @note Any of these events will generate interrupt if Buffer interrupts are enabled too(using unitary function @ref LL_I2C_EnableIT_BUF()) : + * Receive buffer not empty (RXNE) + * Transmit buffer empty (TXE) + * @rmtoll CR2 ITEVTEN LL_I2C_EnableIT_EVT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_EVT(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN); +} + +/** + * @brief Disable Events interrupts. + * @note Any of these events will generate interrupt : + * Start Bit (SB) + * Address sent, Address matched (ADDR) + * 10-bit header sent (ADD10) + * Stop detection (STOPF) + * Byte transfer finished (BTF) + * Receive buffer not empty (RXNE) + * Transmit buffer empty (TXE) + * @rmtoll CR2 ITEVTEN LL_I2C_DisableIT_EVT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_EVT(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN); +} + +/** + * @brief Check if Events interrupts are enabled or disabled. + * @rmtoll CR2 ITEVTEN LL_I2C_IsEnabledIT_EVT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_EVT(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_ITEVTEN) == (I2C_CR2_ITEVTEN)); +} + +/** + * @brief Enable Buffer interrupts. + * @note Any of these Buffer events will generate interrupt if Events interrupts are enabled too(using unitary function @ref LL_I2C_EnableIT_EVT()) : + * Receive buffer not empty (RXNE) + * Transmit buffer empty (TXE) + * @rmtoll CR2 ITBUFEN LL_I2C_EnableIT_BUF + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_BUF(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_ITBUFEN); +} + +/** + * @brief Disable Buffer interrupts. + * @note Any of these Buffer events will generate interrupt : + * Receive buffer not empty (RXNE) + * Transmit buffer empty (TXE) + * @rmtoll CR2 ITBUFEN LL_I2C_DisableIT_BUF + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_BUF(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_ITBUFEN); +} + +/** + * @brief Check if Buffer interrupts are enabled or disabled. + * @rmtoll CR2 ITBUFEN LL_I2C_IsEnabledIT_BUF + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_BUF(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_ITBUFEN) == (I2C_CR2_ITBUFEN)); +} + +/** + * @brief Enable Error interrupts. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note Any of these errors will generate interrupt : + * Bus Error detection (BERR) + * Arbitration Loss (ARLO) + * Acknowledge Failure(AF) + * Overrun/Underrun (OVR) + * SMBus Timeout detection (TIMEOUT) + * SMBus PEC error detection (PECERR) + * SMBus Alert pin event detection (SMBALERT) + * @rmtoll CR2 ITERREN LL_I2C_EnableIT_ERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableIT_ERR(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_ITERREN); +} + +/** + * @brief Disable Error interrupts. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note Any of these errors will generate interrupt : + * Bus Error detection (BERR) + * Arbitration Loss (ARLO) + * Acknowledge Failure(AF) + * Overrun/Underrun (OVR) + * SMBus Timeout detection (TIMEOUT) + * SMBus PEC error detection (PECERR) + * SMBus Alert pin event detection (SMBALERT) + * @rmtoll CR2 ITERREN LL_I2C_DisableIT_ERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableIT_ERR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_ITERREN); +} + +/** + * @brief Check if Error interrupts are enabled or disabled. + * @rmtoll CR2 ITERREN LL_I2C_IsEnabledIT_ERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledIT_ERR(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_ITERREN) == (I2C_CR2_ITERREN)); +} + +/** + * @} + */ + +/** @defgroup I2C_LL_EF_FLAG_management FLAG_management + * @{ + */ + +/** + * @brief Indicate the status of Transmit data register empty flag. + * @note RESET: When next data is written in Transmit data register. + * SET: When Transmit data register is empty. + * @rmtoll SR1 TXE LL_I2C_IsActiveFlag_TXE + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_TXE(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_TXE) == (I2C_SR1_TXE)); +} + +/** + * @brief Indicate the status of Byte Transfer Finished flag. + * RESET: When Data byte transfer not done. + * SET: When Data byte transfer succeeded. + * @rmtoll SR1 BTF LL_I2C_IsActiveFlag_BTF + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BTF(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_BTF) == (I2C_SR1_BTF)); +} + +/** + * @brief Indicate the status of Receive data register not empty flag. + * @note RESET: When Receive data register is read. + * SET: When the received data is copied in Receive data register. + * @rmtoll SR1 RXNE LL_I2C_IsActiveFlag_RXNE + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_RXNE(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_RXNE) == (I2C_SR1_RXNE)); +} + +/** + * @brief Indicate the status of Start Bit (master mode). + * @note RESET: When No Start condition. + * SET: When Start condition is generated. + * @rmtoll SR1 SB LL_I2C_IsActiveFlag_SB + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_SB(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_SB) == (I2C_SR1_SB)); +} + +/** + * @brief Indicate the status of Address sent (master mode) or Address matched flag (slave mode). + * @note RESET: Clear default value. + * SET: When the address is fully sent (master mode) or when the received slave address matched with one of the enabled slave address (slave mode). + * @rmtoll SR1 ADDR LL_I2C_IsActiveFlag_ADDR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ADDR(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_ADDR) == (I2C_SR1_ADDR)); +} + +/** + * @brief Indicate the status of 10-bit header sent (master mode). + * @note RESET: When no ADD10 event occurred. + * SET: When the master has sent the first address byte (header). + * @rmtoll SR1 ADD10 LL_I2C_IsActiveFlag_ADD10 + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ADD10(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_ADD10) == (I2C_SR1_ADD10)); +} + +/** + * @brief Indicate the status of Acknowledge failure flag. + * @note RESET: No acknowledge failure. + * SET: When an acknowledge failure is received after a byte transmission. + * @rmtoll SR1 AF LL_I2C_IsActiveFlag_AF + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_AF(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_AF) == (I2C_SR1_AF)); +} + +/** + * @brief Indicate the status of Stop detection flag (slave mode). + * @note RESET: Clear default value. + * SET: When a Stop condition is detected. + * @rmtoll SR1 STOPF LL_I2C_IsActiveFlag_STOP + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_STOP(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_STOPF) == (I2C_SR1_STOPF)); +} + +/** + * @brief Indicate the status of Bus error flag. + * @note RESET: Clear default value. + * SET: When a misplaced Start or Stop condition is detected. + * @rmtoll SR1 BERR LL_I2C_IsActiveFlag_BERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BERR(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_BERR) == (I2C_SR1_BERR)); +} + +/** + * @brief Indicate the status of Arbitration lost flag. + * @note RESET: Clear default value. + * SET: When arbitration lost. + * @rmtoll SR1 ARLO LL_I2C_IsActiveFlag_ARLO + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_ARLO(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_ARLO) == (I2C_SR1_ARLO)); +} + +/** + * @brief Indicate the status of Overrun/Underrun flag. + * @note RESET: Clear default value. + * SET: When an overrun/underrun error occurs (Clock Stretching Disabled). + * @rmtoll SR1 OVR LL_I2C_IsActiveFlag_OVR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_OVR(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_OVR) == (I2C_SR1_OVR)); +} + +/** + * @brief Indicate the status of SMBus PEC error flag in reception. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR1 PECERR LL_I2C_IsActiveSMBusFlag_PECERR + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_PECERR(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_PECERR) == (I2C_SR1_PECERR)); +} + +/** + * @brief Indicate the status of SMBus Timeout detection flag. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR1 TIMEOUT LL_I2C_IsActiveSMBusFlag_TIMEOUT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_TIMEOUT) == (I2C_SR1_TIMEOUT)); +} + +/** + * @brief Indicate the status of SMBus alert flag. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR1 SMBALERT LL_I2C_IsActiveSMBusFlag_ALERT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_ALERT(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR1, I2C_SR1_SMBALERT) == (I2C_SR1_SMBALERT)); +} + +/** + * @brief Indicate the status of Bus Busy flag. + * @note RESET: Clear default value. + * SET: When a Start condition is detected. + * @rmtoll SR2 BUSY LL_I2C_IsActiveFlag_BUSY + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_BUSY(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_BUSY) == (I2C_SR2_BUSY)); +} + +/** + * @brief Indicate the status of Dual flag. + * @note RESET: Received address matched with OAR1. + * SET: Received address matched with OAR2. + * @rmtoll SR2 DUALF LL_I2C_IsActiveFlag_DUAL + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_DUAL(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_DUALF) == (I2C_SR2_DUALF)); +} + +/** + * @brief Indicate the status of SMBus Host address reception (Slave mode). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note RESET: No SMBus Host address + * SET: SMBus Host address received. + * @note This status is cleared by hardware after a STOP condition or repeated START condition. + * @rmtoll SR2 SMBHOST LL_I2C_IsActiveSMBusFlag_SMBHOST + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_SMBHOST(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_SMBHOST) == (I2C_SR2_SMBHOST)); +} + +/** + * @brief Indicate the status of SMBus Device default address reception (Slave mode). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note RESET: No SMBus Device default address + * SET: SMBus Device default address received. + * @note This status is cleared by hardware after a STOP condition or repeated START condition. + * @rmtoll SR2 SMBDEFAULT LL_I2C_IsActiveSMBusFlag_SMBDEFAULT + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveSMBusFlag_SMBDEFAULT(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_SMBDEFAULT) == (I2C_SR2_SMBDEFAULT)); +} + +/** + * @brief Indicate the status of General call address reception (Slave mode). + * @note RESET: No General call address + * SET: General call address received. + * @note This status is cleared by hardware after a STOP condition or repeated START condition. + * @rmtoll SR2 GENCALL LL_I2C_IsActiveFlag_GENCALL + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_GENCALL(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_GENCALL) == (I2C_SR2_GENCALL)); +} + +/** + * @brief Indicate the status of Master/Slave flag. + * @note RESET: Slave Mode. + * SET: Master Mode. + * @rmtoll SR2 MSL LL_I2C_IsActiveFlag_MSL + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsActiveFlag_MSL(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->SR2, I2C_SR2_MSL) == (I2C_SR2_MSL)); +} + +/** + * @brief Clear Address Matched flag. + * @note Clearing this flag is done by a read access to the I2Cx_SR1 + * register followed by a read access to the I2Cx_SR2 register. + * @rmtoll SR1 ADDR LL_I2C_ClearFlag_ADDR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_ADDR(I2C_TypeDef *I2Cx) +{ + __IO uint32_t tmpreg; + tmpreg = I2Cx->SR1; + (void) tmpreg; + tmpreg = I2Cx->SR2; + (void) tmpreg; +} + +/** + * @brief Clear Acknowledge failure flag. + * @rmtoll SR1 AF LL_I2C_ClearFlag_AF + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_AF(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_AF); +} + +/** + * @brief Clear Stop detection flag. + * @note Clearing this flag is done by a read access to the I2Cx_SR1 + * register followed by a write access to I2Cx_CR1 register. + * @rmtoll SR1 STOPF LL_I2C_ClearFlag_STOP\n + * CR1 PE LL_I2C_ClearFlag_STOP + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_STOP(I2C_TypeDef *I2Cx) +{ + __IO uint32_t tmpreg; + tmpreg = I2Cx->SR1; + (void) tmpreg; + SET_BIT(I2Cx->CR1, I2C_CR1_PE); +} + +/** + * @brief Clear Bus error flag. + * @rmtoll SR1 BERR LL_I2C_ClearFlag_BERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_BERR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_BERR); +} + +/** + * @brief Clear Arbitration lost flag. + * @rmtoll SR1 ARLO LL_I2C_ClearFlag_ARLO + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_ARLO(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_ARLO); +} + +/** + * @brief Clear Overrun/Underrun flag. + * @rmtoll SR1 OVR LL_I2C_ClearFlag_OVR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearFlag_OVR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_OVR); +} + +/** + * @brief Clear SMBus PEC error flag. + * @rmtoll SR1 PECERR LL_I2C_ClearSMBusFlag_PECERR + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_PECERR(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_PECERR); +} + +/** + * @brief Clear SMBus Timeout detection flag. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR1 TIMEOUT LL_I2C_ClearSMBusFlag_TIMEOUT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_TIMEOUT(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_TIMEOUT); +} + +/** + * @brief Clear SMBus Alert flag. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR1 SMBALERT LL_I2C_ClearSMBusFlag_ALERT + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_ClearSMBusFlag_ALERT(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->SR1, I2C_SR1_SMBALERT); +} + +/** + * @} + */ + +/** @defgroup I2C_LL_EF_Data_Management Data_Management + * @{ + */ + +/** + * @brief Enable Reset of I2C peripheral. + * @rmtoll CR1 SWRST LL_I2C_EnableReset + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableReset(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_SWRST); +} + +/** + * @brief Disable Reset of I2C peripheral. + * @rmtoll CR1 SWRST LL_I2C_DisableReset + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableReset(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_SWRST); +} + +/** + * @brief Check if the I2C peripheral is under reset state or not. + * @rmtoll CR1 SWRST LL_I2C_IsResetEnabled + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsResetEnabled(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_SWRST) == (I2C_CR1_SWRST)); +} + +/** + * @brief Prepare the generation of a ACKnowledge or Non ACKnowledge condition after the address receive match code or next received byte. + * @note Usage in Slave or Master mode. + * @rmtoll CR1 ACK LL_I2C_AcknowledgeNextData + * @param I2Cx I2C Instance. + * @param TypeAcknowledge This parameter can be one of the following values: + * @arg @ref LL_I2C_ACK + * @arg @ref LL_I2C_NACK + * @retval None + */ +__STATIC_INLINE void LL_I2C_AcknowledgeNextData(I2C_TypeDef *I2Cx, uint32_t TypeAcknowledge) +{ + MODIFY_REG(I2Cx->CR1, I2C_CR1_ACK, TypeAcknowledge); +} + +/** + * @brief Generate a START or RESTART condition + * @note The START bit can be set even if bus is BUSY or I2C is in slave mode. + * This action has no effect when RELOAD is set. + * @rmtoll CR1 START LL_I2C_GenerateStartCondition + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_GenerateStartCondition(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_START); +} + +/** + * @brief Generate a STOP condition after the current byte transfer (master mode). + * @rmtoll CR1 STOP LL_I2C_GenerateStopCondition + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_GenerateStopCondition(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_STOP); +} + +/** + * @brief Enable bit POS (master/host mode). + * @note In that case, the ACK bit controls the (N)ACK of the next byte received or the PEC bit indicates that the next byte in shift register is a PEC. + * @rmtoll CR1 POS LL_I2C_EnableBitPOS + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableBitPOS(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_POS); +} + +/** + * @brief Disable bit POS (master/host mode). + * @note In that case, the ACK bit controls the (N)ACK of the current byte received or the PEC bit indicates that the current byte in shift register is a PEC. + * @rmtoll CR1 POS LL_I2C_DisableBitPOS + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableBitPOS(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_POS); +} + +/** + * @brief Check if bit POS is enabled or disabled. + * @rmtoll CR1 POS LL_I2C_IsEnabledBitPOS + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledBitPOS(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_POS) == (I2C_CR1_POS)); +} + +/** + * @brief Indicate the value of transfer direction. + * @note RESET: Bus is in read transfer (peripheral point of view). + * SET: Bus is in write transfer (peripheral point of view). + * @rmtoll SR2 TRA LL_I2C_GetTransferDirection + * @param I2Cx I2C Instance. + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2C_DIRECTION_WRITE + * @arg @ref LL_I2C_DIRECTION_READ + */ +__STATIC_INLINE uint32_t LL_I2C_GetTransferDirection(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->SR2, I2C_SR2_TRA)); +} + +/** + * @brief Enable DMA last transfer. + * @note This action mean that next DMA EOT is the last transfer. + * @rmtoll CR2 LAST LL_I2C_EnableLastDMA + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableLastDMA(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR2, I2C_CR2_LAST); +} + +/** + * @brief Disable DMA last transfer. + * @note This action mean that next DMA EOT is not the last transfer. + * @rmtoll CR2 LAST LL_I2C_DisableLastDMA + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableLastDMA(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR2, I2C_CR2_LAST); +} + +/** + * @brief Check if DMA last transfer is enabled or disabled. + * @rmtoll CR2 LAST LL_I2C_IsEnabledLastDMA + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledLastDMA(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR2, I2C_CR2_LAST) == (I2C_CR2_LAST)); +} + +/** + * @brief Enable transfer or internal comparison of the SMBus Packet Error byte (transmission or reception mode). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @note This feature is cleared by hardware when the PEC byte is transferred or compared, + * or by a START or STOP condition, it is also cleared by software. + * @rmtoll CR1 PEC LL_I2C_EnableSMBusPECCompare + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_EnableSMBusPECCompare(I2C_TypeDef *I2Cx) +{ + SET_BIT(I2Cx->CR1, I2C_CR1_PEC); +} + +/** + * @brief Disable transfer or internal comparison of the SMBus Packet Error byte (transmission or reception mode). + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 PEC LL_I2C_DisableSMBusPECCompare + * @param I2Cx I2C Instance. + * @retval None + */ +__STATIC_INLINE void LL_I2C_DisableSMBusPECCompare(I2C_TypeDef *I2Cx) +{ + CLEAR_BIT(I2Cx->CR1, I2C_CR1_PEC); +} + +/** + * @brief Check if the SMBus Packet Error byte transfer or internal comparison is requested or not. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll CR1 PEC LL_I2C_IsEnabledSMBusPECCompare + * @param I2Cx I2C Instance. + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2C_IsEnabledSMBusPECCompare(I2C_TypeDef *I2Cx) +{ + return (READ_BIT(I2Cx->CR1, I2C_CR1_PEC) == (I2C_CR1_PEC)); +} + +/** + * @brief Get the SMBus Packet Error byte calculated. + * @note Macro @ref IS_SMBUS_ALL_INSTANCE(I2Cx) can be used to check whether or not + * SMBus feature is supported by the I2Cx Instance. + * @rmtoll SR2 PEC LL_I2C_GetSMBusPEC + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2C_GetSMBusPEC(I2C_TypeDef *I2Cx) +{ + return (uint32_t)(READ_BIT(I2Cx->SR2, I2C_SR2_PEC) >> I2C_SR2_PEC_Pos); +} + +/** + * @brief Read Receive Data register. + * @rmtoll DR DR LL_I2C_ReceiveData8 + * @param I2Cx I2C Instance. + * @retval Value between Min_Data=0x0 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_I2C_ReceiveData8(I2C_TypeDef *I2Cx) +{ + return (uint8_t)(READ_BIT(I2Cx->DR, I2C_DR_DR)); +} + +/** + * @brief Write in Transmit Data Register . + * @rmtoll DR DR LL_I2C_TransmitData8 + * @param I2Cx I2C Instance. + * @param Data Value between Min_Data=0x0 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_I2C_TransmitData8(I2C_TypeDef *I2Cx, uint8_t Data) +{ + MODIFY_REG(I2Cx->DR, I2C_DR_DR, Data); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2C_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +uint32_t LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct); +uint32_t LL_I2C_DeInit(I2C_TypeDef *I2Cx); +void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct); + + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* I2C1 || I2C2 || I2C3 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_LL_I2C_H */ + diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h new file mode 100644 index 0000000..4158363 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_iwdg.h @@ -0,0 +1,302 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_iwdg.h + * @author MCD Application Team + * @brief Header file of IWDG 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 STM32F4xx_LL_IWDG_H +#define STM32F4xx_LL_IWDG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(IWDG) + +/** @defgroup IWDG_LL IWDG + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup IWDG_LL_Private_Constants IWDG Private Constants + * @{ + */ +#define LL_IWDG_KEY_RELOAD 0x0000AAAAU /*!< IWDG Reload Counter Enable */ +#define LL_IWDG_KEY_ENABLE 0x0000CCCCU /*!< IWDG Peripheral Enable */ +#define LL_IWDG_KEY_WR_ACCESS_ENABLE 0x00005555U /*!< IWDG KR Write Access Enable */ +#define LL_IWDG_KEY_WR_ACCESS_DISABLE 0x00000000U /*!< IWDG KR Write Access Disable */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup IWDG_LL_Exported_Constants IWDG Exported Constants + * @{ + */ + +/** @defgroup IWDG_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_IWDG_ReadReg function + * @{ + */ +#define LL_IWDG_SR_PVU IWDG_SR_PVU /*!< Watchdog prescaler value update */ +#define LL_IWDG_SR_RVU IWDG_SR_RVU /*!< Watchdog counter reload value update */ +/** + * @} + */ + +/** @defgroup IWDG_LL_EC_PRESCALER Prescaler Divider + * @{ + */ +#define LL_IWDG_PRESCALER_4 0x00000000U /*!< Divider by 4 */ +#define LL_IWDG_PRESCALER_8 (IWDG_PR_PR_0) /*!< Divider by 8 */ +#define LL_IWDG_PRESCALER_16 (IWDG_PR_PR_1) /*!< Divider by 16 */ +#define LL_IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< Divider by 32 */ +#define LL_IWDG_PRESCALER_64 (IWDG_PR_PR_2) /*!< Divider by 64 */ +#define LL_IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< Divider by 128 */ +#define LL_IWDG_PRESCALER_256 (IWDG_PR_PR_2 | IWDG_PR_PR_1) /*!< Divider by 256 */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup IWDG_LL_Exported_Macros IWDG Exported Macros + * @{ + */ + +/** @defgroup IWDG_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in IWDG register + * @param __INSTANCE__ IWDG Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_IWDG_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in IWDG register + * @param __INSTANCE__ IWDG Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_IWDG_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup IWDG_LL_Exported_Functions IWDG Exported Functions + * @{ + */ +/** @defgroup IWDG_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Start the Independent Watchdog + * @note Except if the hardware watchdog option is selected + * @rmtoll KR KEY LL_IWDG_Enable + * @param IWDGx IWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_IWDG_Enable(IWDG_TypeDef *IWDGx) +{ + WRITE_REG(IWDGx->KR, LL_IWDG_KEY_ENABLE); +} + +/** + * @brief Reloads IWDG counter with value defined in the reload register + * @rmtoll KR KEY LL_IWDG_ReloadCounter + * @param IWDGx IWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_IWDG_ReloadCounter(IWDG_TypeDef *IWDGx) +{ + WRITE_REG(IWDGx->KR, LL_IWDG_KEY_RELOAD); +} + +/** + * @brief Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers + * @rmtoll KR KEY LL_IWDG_EnableWriteAccess + * @param IWDGx IWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_IWDG_EnableWriteAccess(IWDG_TypeDef *IWDGx) +{ + WRITE_REG(IWDGx->KR, LL_IWDG_KEY_WR_ACCESS_ENABLE); +} + +/** + * @brief Disable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers + * @rmtoll KR KEY LL_IWDG_DisableWriteAccess + * @param IWDGx IWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_IWDG_DisableWriteAccess(IWDG_TypeDef *IWDGx) +{ + WRITE_REG(IWDGx->KR, LL_IWDG_KEY_WR_ACCESS_DISABLE); +} + +/** + * @brief Select the prescaler of the IWDG + * @rmtoll PR PR LL_IWDG_SetPrescaler + * @param IWDGx IWDG Instance + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_IWDG_PRESCALER_4 + * @arg @ref LL_IWDG_PRESCALER_8 + * @arg @ref LL_IWDG_PRESCALER_16 + * @arg @ref LL_IWDG_PRESCALER_32 + * @arg @ref LL_IWDG_PRESCALER_64 + * @arg @ref LL_IWDG_PRESCALER_128 + * @arg @ref LL_IWDG_PRESCALER_256 + * @retval None + */ +__STATIC_INLINE void LL_IWDG_SetPrescaler(IWDG_TypeDef *IWDGx, uint32_t Prescaler) +{ + WRITE_REG(IWDGx->PR, IWDG_PR_PR & Prescaler); +} + +/** + * @brief Get the selected prescaler of the IWDG + * @rmtoll PR PR LL_IWDG_GetPrescaler + * @param IWDGx IWDG Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_IWDG_PRESCALER_4 + * @arg @ref LL_IWDG_PRESCALER_8 + * @arg @ref LL_IWDG_PRESCALER_16 + * @arg @ref LL_IWDG_PRESCALER_32 + * @arg @ref LL_IWDG_PRESCALER_64 + * @arg @ref LL_IWDG_PRESCALER_128 + * @arg @ref LL_IWDG_PRESCALER_256 + */ +__STATIC_INLINE uint32_t LL_IWDG_GetPrescaler(IWDG_TypeDef *IWDGx) +{ + return (READ_REG(IWDGx->PR)); +} + +/** + * @brief Specify the IWDG down-counter reload value + * @rmtoll RLR RL LL_IWDG_SetReloadCounter + * @param IWDGx IWDG Instance + * @param Counter Value between Min_Data=0 and Max_Data=0x0FFF + * @retval None + */ +__STATIC_INLINE void LL_IWDG_SetReloadCounter(IWDG_TypeDef *IWDGx, uint32_t Counter) +{ + WRITE_REG(IWDGx->RLR, IWDG_RLR_RL & Counter); +} + +/** + * @brief Get the specified IWDG down-counter reload value + * @rmtoll RLR RL LL_IWDG_GetReloadCounter + * @param IWDGx IWDG Instance + * @retval Value between Min_Data=0 and Max_Data=0x0FFF + */ +__STATIC_INLINE uint32_t LL_IWDG_GetReloadCounter(IWDG_TypeDef *IWDGx) +{ + return (READ_REG(IWDGx->RLR)); +} + +/** + * @} + */ + +/** @defgroup IWDG_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Check if flag Prescaler Value Update is set or not + * @rmtoll SR PVU LL_IWDG_IsActiveFlag_PVU + * @param IWDGx IWDG Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_IWDG_IsActiveFlag_PVU(IWDG_TypeDef *IWDGx) +{ + return ((READ_BIT(IWDGx->SR, IWDG_SR_PVU) == (IWDG_SR_PVU)) ? 1UL : 0UL); +} + +/** + * @brief Check if flag Reload Value Update is set or not + * @rmtoll SR RVU LL_IWDG_IsActiveFlag_RVU + * @param IWDGx IWDG Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_IWDG_IsActiveFlag_RVU(IWDG_TypeDef *IWDGx) +{ + return ((READ_BIT(IWDGx->SR, IWDG_SR_RVU) == (IWDG_SR_RVU)) ? 1UL : 0UL); +} + +/** + * @brief Check if flags Prescaler & Reload Value Update are reset or not + * @rmtoll SR PVU LL_IWDG_IsReady\n + * SR RVU LL_IWDG_IsReady + * @param IWDGx IWDG Instance + * @retval State of bits (1 or 0). + */ +__STATIC_INLINE uint32_t LL_IWDG_IsReady(IWDG_TypeDef *IWDGx) +{ + return ((READ_BIT(IWDGx->SR, IWDG_SR_PVU | IWDG_SR_RVU) == 0U) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* IWDG */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_IWDG_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h new file mode 100644 index 0000000..f84ed6b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_lptim.h @@ -0,0 +1,1378 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_lptim.h + * @author MCD Application Team + * @brief Header file of LPTIM 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 STM32F4xx_LL_LPTIM_H +#define STM32F4xx_LL_LPTIM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (LPTIM1) + +/** @defgroup LPTIM_LL LPTIM + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ + +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup LPTIM_LL_Private_Macros LPTIM Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup LPTIM_LL_ES_INIT LPTIM Exported Init structure + * @{ + */ + +/** + * @brief LPTIM Init structure definition + */ +typedef struct +{ + uint32_t ClockSource; /*!< Specifies the source of the clock used by the LPTIM instance. + This parameter can be a value of @ref LPTIM_LL_EC_CLK_SOURCE. + + This feature can be modified afterwards using unitary + function @ref LL_LPTIM_SetClockSource().*/ + + uint32_t Prescaler; /*!< Specifies the prescaler division ratio. + This parameter can be a value of @ref LPTIM_LL_EC_PRESCALER. + + This feature can be modified afterwards using using unitary + function @ref LL_LPTIM_SetPrescaler().*/ + + uint32_t Waveform; /*!< Specifies the waveform shape. + This parameter can be a value of @ref LPTIM_LL_EC_OUTPUT_WAVEFORM. + + This feature can be modified afterwards using unitary + function @ref LL_LPTIM_ConfigOutput().*/ + + uint32_t Polarity; /*!< Specifies waveform polarity. + This parameter can be a value of @ref LPTIM_LL_EC_OUTPUT_POLARITY. + + This feature can be modified afterwards using unitary + function @ref LL_LPTIM_ConfigOutput().*/ +} LL_LPTIM_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup LPTIM_LL_Exported_Constants LPTIM Exported Constants + * @{ + */ + +/** @defgroup LPTIM_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_LPTIM_ReadReg function + * @{ + */ +#define LL_LPTIM_ISR_CMPM LPTIM_ISR_CMPM /*!< Compare match */ +#define LL_LPTIM_ISR_CMPOK LPTIM_ISR_CMPOK /*!< Compare register update OK */ +#define LL_LPTIM_ISR_ARRM LPTIM_ISR_ARRM /*!< Autoreload match */ +#define LL_LPTIM_ISR_EXTTRIG LPTIM_ISR_EXTTRIG /*!< External trigger edge event */ +#define LL_LPTIM_ISR_ARROK LPTIM_ISR_ARROK /*!< Autoreload register update OK */ +#define LL_LPTIM_ISR_UP LPTIM_ISR_UP /*!< Counter direction change down to up */ +#define LL_LPTIM_ISR_DOWN LPTIM_ISR_DOWN /*!< Counter direction change up to down */ +/** + * @} + */ + +/** @defgroup LPTIM_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_LPTIM_ReadReg and LL_LPTIM_WriteReg functions + * @{ + */ +#define LL_LPTIM_IER_CMPMIE LPTIM_IER_CMPMIE /*!< Compare match */ +#define LL_LPTIM_IER_CMPOKIE LPTIM_IER_CMPOKIE /*!< Compare register update OK */ +#define LL_LPTIM_IER_ARRMIE LPTIM_IER_ARRMIE /*!< Autoreload match */ +#define LL_LPTIM_IER_EXTTRIGIE LPTIM_IER_EXTTRIGIE /*!< External trigger edge event */ +#define LL_LPTIM_IER_ARROKIE LPTIM_IER_ARROKIE /*!< Autoreload register update OK */ +#define LL_LPTIM_IER_UPIE LPTIM_IER_UPIE /*!< Counter direction change down to up */ +#define LL_LPTIM_IER_DOWNIE LPTIM_IER_DOWNIE /*!< Counter direction change up to down */ +/** + * @} + */ + +/** @defgroup LPTIM_LL_EC_OPERATING_MODE Operating Mode + * @{ + */ +#define LL_LPTIM_OPERATING_MODE_CONTINUOUS LPTIM_CR_CNTSTRT /*!__REG__, (__VALUE__)) + +/** + * @brief Read a value in LPTIM register + * @param __INSTANCE__ LPTIM Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_LPTIM_ReadReg(__INSTANCE__, __REG__) READ_REG((__INSTANCE__)->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup LPTIM_LL_Exported_Functions LPTIM Exported Functions + * @{ + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup LPTIM_LL_EF_Init Initialisation and deinitialisation functions + * @{ + */ + +ErrorStatus LL_LPTIM_DeInit(LPTIM_TypeDef *LPTIMx); +void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct); +ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, const LL_LPTIM_InitTypeDef *LPTIM_InitStruct); +void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx); +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup LPTIM_LL_EF_LPTIM_Configuration LPTIM Configuration + * @{ + */ + +/** + * @brief Enable the LPTIM instance + * @note After setting the ENABLE bit, a delay of two counter clock is needed + * before the LPTIM instance is actually enabled. + * @rmtoll CR ENABLE LL_LPTIM_Enable + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_Enable(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->CR, LPTIM_CR_ENABLE); +} + +/** + * @brief Indicates whether the LPTIM instance is enabled. + * @rmtoll CR ENABLE LL_LPTIM_IsEnabled + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabled(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->CR, LPTIM_CR_ENABLE) == LPTIM_CR_ENABLE) ? 1UL : 0UL)); +} + +/** + * @brief Starts the LPTIM counter in the desired mode. + * @note LPTIM instance must be enabled before starting the counter. + * @note It is possible to change on the fly from One Shot mode to + * Continuous mode. + * @rmtoll CR CNTSTRT LL_LPTIM_StartCounter\n + * CR SNGSTRT LL_LPTIM_StartCounter + * @param LPTIMx Low-Power Timer instance + * @param OperatingMode This parameter can be one of the following values: + * @arg @ref LL_LPTIM_OPERATING_MODE_CONTINUOUS + * @arg @ref LL_LPTIM_OPERATING_MODE_ONESHOT + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_StartCounter(LPTIM_TypeDef *LPTIMx, uint32_t OperatingMode) +{ + MODIFY_REG(LPTIMx->CR, LPTIM_CR_CNTSTRT | LPTIM_CR_SNGSTRT, OperatingMode); +} + +/** + * @brief Set the LPTIM registers update mode (enable/disable register preload) + * @note This function must be called when the LPTIM instance is disabled. + * @rmtoll CFGR PRELOAD LL_LPTIM_SetUpdateMode + * @param LPTIMx Low-Power Timer instance + * @param UpdateMode This parameter can be one of the following values: + * @arg @ref LL_LPTIM_UPDATE_MODE_IMMEDIATE + * @arg @ref LL_LPTIM_UPDATE_MODE_ENDOFPERIOD + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetUpdateMode(LPTIM_TypeDef *LPTIMx, uint32_t UpdateMode) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_PRELOAD, UpdateMode); +} + +/** + * @brief Get the LPTIM registers update mode + * @rmtoll CFGR PRELOAD LL_LPTIM_GetUpdateMode + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_UPDATE_MODE_IMMEDIATE + * @arg @ref LL_LPTIM_UPDATE_MODE_ENDOFPERIOD + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetUpdateMode(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_PRELOAD)); +} + +/** + * @brief Set the auto reload value + * @note The LPTIMx_ARR register content must only be modified when the LPTIM is enabled + * @note After a write to the LPTIMx_ARR register a new write operation to the + * same register can only be performed when the previous write operation + * is completed. Any successive write before the ARROK flag is set, will + * lead to unpredictable results. + * @note autoreload value be strictly greater than the compare value. + * @rmtoll ARR ARR LL_LPTIM_SetAutoReload + * @param LPTIMx Low-Power Timer instance + * @param AutoReload Value between Min_Data=0x0001 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetAutoReload(LPTIM_TypeDef *LPTIMx, uint32_t AutoReload) +{ + MODIFY_REG(LPTIMx->ARR, LPTIM_ARR_ARR, AutoReload); +} + +/** + * @brief Get actual auto reload value + * @rmtoll ARR ARR LL_LPTIM_GetAutoReload + * @param LPTIMx Low-Power Timer instance + * @retval AutoReload Value between Min_Data=0x0001 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetAutoReload(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->ARR, LPTIM_ARR_ARR)); +} + +/** + * @brief Set the compare value + * @note After a write to the LPTIMx_CMP register a new write operation to the + * same register can only be performed when the previous write operation + * is completed. Any successive write before the CMPOK flag is set, will + * lead to unpredictable results. + * @rmtoll CMP CMP LL_LPTIM_SetCompare + * @param LPTIMx Low-Power Timer instance + * @param CompareValue Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetCompare(LPTIM_TypeDef *LPTIMx, uint32_t CompareValue) +{ + MODIFY_REG(LPTIMx->CMP, LPTIM_CMP_CMP, CompareValue); +} + +/** + * @brief Get actual compare value + * @rmtoll CMP CMP LL_LPTIM_GetCompare + * @param LPTIMx Low-Power Timer instance + * @retval CompareValue Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetCompare(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CMP, LPTIM_CMP_CMP)); +} + +/** + * @brief Get actual counter value + * @note When the LPTIM instance is running with an asynchronous clock, reading + * the LPTIMx_CNT register may return unreliable values. So in this case + * it is necessary to perform two consecutive read accesses and verify + * that the two returned values are identical. + * @rmtoll CNT CNT LL_LPTIM_GetCounter + * @param LPTIMx Low-Power Timer instance + * @retval Counter value + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetCounter(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CNT, LPTIM_CNT_CNT)); +} + +/** + * @brief Set the counter mode (selection of the LPTIM counter clock source). + * @note The counter mode can be set only when the LPTIM instance is disabled. + * @rmtoll CFGR COUNTMODE LL_LPTIM_SetCounterMode + * @param LPTIMx Low-Power Timer instance + * @param CounterMode This parameter can be one of the following values: + * @arg @ref LL_LPTIM_COUNTER_MODE_INTERNAL + * @arg @ref LL_LPTIM_COUNTER_MODE_EXTERNAL + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetCounterMode(LPTIM_TypeDef *LPTIMx, uint32_t CounterMode) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_COUNTMODE, CounterMode); +} + +/** + * @brief Get the counter mode + * @rmtoll CFGR COUNTMODE LL_LPTIM_GetCounterMode + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_COUNTER_MODE_INTERNAL + * @arg @ref LL_LPTIM_COUNTER_MODE_EXTERNAL + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetCounterMode(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_COUNTMODE)); +} + +/** + * @brief Configure the LPTIM instance output (LPTIMx_OUT) + * @note This function must be called when the LPTIM instance is disabled. + * @note Regarding the LPTIM output polarity the change takes effect + * immediately, so the output default value will change immediately after + * the polarity is re-configured, even before the timer is enabled. + * @rmtoll CFGR WAVE LL_LPTIM_ConfigOutput\n + * CFGR WAVPOL LL_LPTIM_ConfigOutput + * @param LPTIMx Low-Power Timer instance + * @param Waveform This parameter can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_PWM + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_SETONCE + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_REGULAR + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_INVERSE + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ConfigOutput(LPTIM_TypeDef *LPTIMx, uint32_t Waveform, uint32_t Polarity) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL, Waveform | Polarity); +} + +/** + * @brief Set waveform shape + * @rmtoll CFGR WAVE LL_LPTIM_SetWaveform + * @param LPTIMx Low-Power Timer instance + * @param Waveform This parameter can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_PWM + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_SETONCE + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetWaveform(LPTIM_TypeDef *LPTIMx, uint32_t Waveform) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_WAVE, Waveform); +} + +/** + * @brief Get actual waveform shape + * @rmtoll CFGR WAVE LL_LPTIM_GetWaveform + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_PWM + * @arg @ref LL_LPTIM_OUTPUT_WAVEFORM_SETONCE + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetWaveform(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_WAVE)); +} + +/** + * @brief Set output polarity + * @rmtoll CFGR WAVPOL LL_LPTIM_SetPolarity + * @param LPTIMx Low-Power Timer instance + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_REGULAR + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_INVERSE + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetPolarity(LPTIM_TypeDef *LPTIMx, uint32_t Polarity) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_WAVPOL, Polarity); +} + +/** + * @brief Get actual output polarity + * @rmtoll CFGR WAVPOL LL_LPTIM_GetPolarity + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_REGULAR + * @arg @ref LL_LPTIM_OUTPUT_POLARITY_INVERSE + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetPolarity(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_WAVPOL)); +} + +/** + * @brief Set actual prescaler division ratio. + * @note This function must be called when the LPTIM instance is disabled. + * @note When the LPTIM is configured to be clocked by an internal clock source + * and the LPTIM counter is configured to be updated by active edges + * detected on the LPTIM external Input1, the internal clock provided to + * the LPTIM must be not be prescaled. + * @rmtoll CFGR PRESC LL_LPTIM_SetPrescaler + * @param LPTIMx Low-Power Timer instance + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_LPTIM_PRESCALER_DIV1 + * @arg @ref LL_LPTIM_PRESCALER_DIV2 + * @arg @ref LL_LPTIM_PRESCALER_DIV4 + * @arg @ref LL_LPTIM_PRESCALER_DIV8 + * @arg @ref LL_LPTIM_PRESCALER_DIV16 + * @arg @ref LL_LPTIM_PRESCALER_DIV32 + * @arg @ref LL_LPTIM_PRESCALER_DIV64 + * @arg @ref LL_LPTIM_PRESCALER_DIV128 + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetPrescaler(LPTIM_TypeDef *LPTIMx, uint32_t Prescaler) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_PRESC, Prescaler); +} + +/** + * @brief Get actual prescaler division ratio. + * @rmtoll CFGR PRESC LL_LPTIM_GetPrescaler + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_PRESCALER_DIV1 + * @arg @ref LL_LPTIM_PRESCALER_DIV2 + * @arg @ref LL_LPTIM_PRESCALER_DIV4 + * @arg @ref LL_LPTIM_PRESCALER_DIV8 + * @arg @ref LL_LPTIM_PRESCALER_DIV16 + * @arg @ref LL_LPTIM_PRESCALER_DIV32 + * @arg @ref LL_LPTIM_PRESCALER_DIV64 + * @arg @ref LL_LPTIM_PRESCALER_DIV128 + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetPrescaler(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_PRESC)); +} + +/** + * @brief Set LPTIM input 1 source (default GPIO). + * @rmtoll OR OR LL_LPTIM_SetInput1Src + * @param LPTIMx Low-Power Timer instance + * @param Src This parameter can be one of the following values: + * @arg @ref LL_LPTIM_INPUT1_SRC_PAD_AF + * @arg @ref LL_LPTIM_INPUT1_SRC_PAD_PA4 + * @arg @ref LL_LPTIM_INPUT1_SRC_PAD_PB9 + * @arg @ref LL_LPTIM_INPUT1_SRC_TIM_DAC + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetInput1Src(LPTIM_TypeDef *LPTIMx, uint32_t Src) +{ + MODIFY_REG(LPTIMx->OR, LPTIM_OR_OR, Src); +} + +/** + * @} + */ + +/** @defgroup LPTIM_LL_EF_Trigger_Configuration Trigger Configuration + * @{ + */ + +/** + * @brief Enable the timeout function + * @note This function must be called when the LPTIM instance is disabled. + * @note The first trigger event will start the timer, any successive trigger + * event will reset the counter and the timer will restart. + * @note The timeout value corresponds to the compare value; if no trigger + * occurs within the expected time frame, the MCU is waked-up by the + * compare match event. + * @rmtoll CFGR TIMOUT LL_LPTIM_EnableTimeout + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableTimeout(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->CFGR, LPTIM_CFGR_TIMOUT); +} + +/** + * @brief Disable the timeout function + * @note This function must be called when the LPTIM instance is disabled. + * @note A trigger event arriving when the timer is already started will be + * ignored. + * @rmtoll CFGR TIMOUT LL_LPTIM_DisableTimeout + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableTimeout(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->CFGR, LPTIM_CFGR_TIMOUT); +} + +/** + * @brief Indicate whether the timeout function is enabled. + * @rmtoll CFGR TIMOUT LL_LPTIM_IsEnabledTimeout + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledTimeout(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_TIMOUT) == LPTIM_CFGR_TIMOUT) ? 1UL : 0UL)); +} + +/** + * @brief Start the LPTIM counter + * @note This function must be called when the LPTIM instance is disabled. + * @rmtoll CFGR TRIGEN LL_LPTIM_TrigSw + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_TrigSw(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->CFGR, LPTIM_CFGR_TRIGEN); +} + +/** + * @brief Configure the external trigger used as a trigger event for the LPTIM. + * @note This function must be called when the LPTIM instance is disabled. + * @note An internal clock source must be present when a digital filter is + * required for the trigger. + * @rmtoll CFGR TRIGSEL LL_LPTIM_ConfigTrigger\n + * CFGR TRGFLT LL_LPTIM_ConfigTrigger\n + * CFGR TRIGEN LL_LPTIM_ConfigTrigger + * @param LPTIMx Low-Power Timer instance + * @param Source This parameter can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_SOURCE_GPIO + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCALARMA + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCALARMB + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCTAMP1 + * @arg @ref LL_LPTIM_TRIG_SOURCE_TIM1_TRGO + * @arg @ref LL_LPTIM_TRIG_SOURCE_TIM5_TRGO + * @param Filter This parameter can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_FILTER_NONE + * @arg @ref LL_LPTIM_TRIG_FILTER_2 + * @arg @ref LL_LPTIM_TRIG_FILTER_4 + * @arg @ref LL_LPTIM_TRIG_FILTER_8 + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_POLARITY_RISING + * @arg @ref LL_LPTIM_TRIG_POLARITY_FALLING + * @arg @ref LL_LPTIM_TRIG_POLARITY_RISING_FALLING + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ConfigTrigger(LPTIM_TypeDef *LPTIMx, uint32_t Source, uint32_t Filter, uint32_t Polarity) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_TRIGSEL | LPTIM_CFGR_TRGFLT | LPTIM_CFGR_TRIGEN, Source | Filter | Polarity); +} + +/** + * @brief Get actual external trigger source. + * @rmtoll CFGR TRIGSEL LL_LPTIM_GetTriggerSource + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_SOURCE_GPIO + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCALARMA + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCALARMB + * @arg @ref LL_LPTIM_TRIG_SOURCE_RTCTAMP1 + * @arg @ref LL_LPTIM_TRIG_SOURCE_TIM1_TRGO + * @arg @ref LL_LPTIM_TRIG_SOURCE_TIM5_TRGO + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetTriggerSource(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_TRIGSEL)); +} + +/** + * @brief Get actual external trigger filter. + * @rmtoll CFGR TRGFLT LL_LPTIM_GetTriggerFilter + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_FILTER_NONE + * @arg @ref LL_LPTIM_TRIG_FILTER_2 + * @arg @ref LL_LPTIM_TRIG_FILTER_4 + * @arg @ref LL_LPTIM_TRIG_FILTER_8 + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetTriggerFilter(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_TRGFLT)); +} + +/** + * @brief Get actual external trigger polarity. + * @rmtoll CFGR TRIGEN LL_LPTIM_GetTriggerPolarity + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_TRIG_POLARITY_RISING + * @arg @ref LL_LPTIM_TRIG_POLARITY_FALLING + * @arg @ref LL_LPTIM_TRIG_POLARITY_RISING_FALLING + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetTriggerPolarity(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_TRIGEN)); +} + +/** + * @} + */ + +/** @defgroup LPTIM_LL_EF_Clock_Configuration Clock Configuration + * @{ + */ + +/** + * @brief Set the source of the clock used by the LPTIM instance. + * @note This function must be called when the LPTIM instance is disabled. + * @rmtoll CFGR CKSEL LL_LPTIM_SetClockSource + * @param LPTIMx Low-Power Timer instance + * @param ClockSource This parameter can be one of the following values: + * @arg @ref LL_LPTIM_CLK_SOURCE_INTERNAL + * @arg @ref LL_LPTIM_CLK_SOURCE_EXTERNAL + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetClockSource(LPTIM_TypeDef *LPTIMx, uint32_t ClockSource) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_CKSEL, ClockSource); +} + +/** + * @brief Get actual LPTIM instance clock source. + * @rmtoll CFGR CKSEL LL_LPTIM_GetClockSource + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_CLK_SOURCE_INTERNAL + * @arg @ref LL_LPTIM_CLK_SOURCE_EXTERNAL + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetClockSource(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_CKSEL)); +} + +/** + * @brief Configure the active edge or edges used by the counter when + the LPTIM is clocked by an external clock source. + * @note This function must be called when the LPTIM instance is disabled. + * @note When both external clock signal edges are considered active ones, + * the LPTIM must also be clocked by an internal clock source with a + * frequency equal to at least four times the external clock frequency. + * @note An internal clock source must be present when a digital filter is + * required for external clock. + * @rmtoll CFGR CKFLT LL_LPTIM_ConfigClock\n + * CFGR CKPOL LL_LPTIM_ConfigClock + * @param LPTIMx Low-Power Timer instance + * @param ClockFilter This parameter can be one of the following values: + * @arg @ref LL_LPTIM_CLK_FILTER_NONE + * @arg @ref LL_LPTIM_CLK_FILTER_2 + * @arg @ref LL_LPTIM_CLK_FILTER_4 + * @arg @ref LL_LPTIM_CLK_FILTER_8 + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_LPTIM_CLK_POLARITY_RISING + * @arg @ref LL_LPTIM_CLK_POLARITY_FALLING + * @arg @ref LL_LPTIM_CLK_POLARITY_RISING_FALLING + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ConfigClock(LPTIM_TypeDef *LPTIMx, uint32_t ClockFilter, uint32_t ClockPolarity) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_CKFLT | LPTIM_CFGR_CKPOL, ClockFilter | ClockPolarity); +} + +/** + * @brief Get actual clock polarity + * @rmtoll CFGR CKPOL LL_LPTIM_GetClockPolarity + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_CLK_POLARITY_RISING + * @arg @ref LL_LPTIM_CLK_POLARITY_FALLING + * @arg @ref LL_LPTIM_CLK_POLARITY_RISING_FALLING + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetClockPolarity(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_CKPOL)); +} + +/** + * @brief Get actual clock digital filter + * @rmtoll CFGR CKFLT LL_LPTIM_GetClockFilter + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_CLK_FILTER_NONE + * @arg @ref LL_LPTIM_CLK_FILTER_2 + * @arg @ref LL_LPTIM_CLK_FILTER_4 + * @arg @ref LL_LPTIM_CLK_FILTER_8 + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetClockFilter(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_CKFLT)); +} + +/** + * @} + */ + +/** @defgroup LPTIM_LL_EF_Encoder_Mode Encoder Mode + * @{ + */ + +/** + * @brief Configure the encoder mode. + * @note This function must be called when the LPTIM instance is disabled. + * @rmtoll CFGR CKPOL LL_LPTIM_SetEncoderMode + * @param LPTIMx Low-Power Timer instance + * @param EncoderMode This parameter can be one of the following values: + * @arg @ref LL_LPTIM_ENCODER_MODE_RISING + * @arg @ref LL_LPTIM_ENCODER_MODE_FALLING + * @arg @ref LL_LPTIM_ENCODER_MODE_RISING_FALLING + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_SetEncoderMode(LPTIM_TypeDef *LPTIMx, uint32_t EncoderMode) +{ + MODIFY_REG(LPTIMx->CFGR, LPTIM_CFGR_CKPOL, EncoderMode); +} + +/** + * @brief Get actual encoder mode. + * @rmtoll CFGR CKPOL LL_LPTIM_GetEncoderMode + * @param LPTIMx Low-Power Timer instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_LPTIM_ENCODER_MODE_RISING + * @arg @ref LL_LPTIM_ENCODER_MODE_FALLING + * @arg @ref LL_LPTIM_ENCODER_MODE_RISING_FALLING + */ +__STATIC_INLINE uint32_t LL_LPTIM_GetEncoderMode(const LPTIM_TypeDef *LPTIMx) +{ + return (uint32_t)(READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_CKPOL)); +} + +/** + * @brief Enable the encoder mode + * @note This function must be called when the LPTIM instance is disabled. + * @note In this mode the LPTIM instance must be clocked by an internal clock + * source. Also, the prescaler division ratio must be equal to 1. + * @note LPTIM instance must be configured in continuous mode prior enabling + * the encoder mode. + * @rmtoll CFGR ENC LL_LPTIM_EnableEncoderMode + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableEncoderMode(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->CFGR, LPTIM_CFGR_ENC); +} + +/** + * @brief Disable the encoder mode + * @note This function must be called when the LPTIM instance is disabled. + * @rmtoll CFGR ENC LL_LPTIM_DisableEncoderMode + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableEncoderMode(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->CFGR, LPTIM_CFGR_ENC); +} + +/** + * @brief Indicates whether the LPTIM operates in encoder mode. + * @rmtoll CFGR ENC LL_LPTIM_IsEnabledEncoderMode + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledEncoderMode(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->CFGR, LPTIM_CFGR_ENC) == LPTIM_CFGR_ENC) ? 1UL : 0UL)); +} + +/** + * @} + */ + +/** @defgroup LPTIM_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Clear the compare match flag (CMPMCF) + * @rmtoll ICR CMPMCF LL_LPTIM_ClearFLAG_CMPM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFLAG_CMPM(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_CMPMCF); +} + +/** + * @brief Inform application whether a compare match interrupt has occurred. + * @rmtoll ISR CMPM LL_LPTIM_IsActiveFlag_CMPM + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_CMPM(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_CMPM) == LPTIM_ISR_CMPM) ? 1UL : 0UL)); +} + +/** + * @brief Clear the autoreload match flag (ARRMCF) + * @rmtoll ICR ARRMCF LL_LPTIM_ClearFLAG_ARRM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFLAG_ARRM(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_ARRMCF); +} + +/** + * @brief Inform application whether a autoreload match interrupt has occurred. + * @rmtoll ISR ARRM LL_LPTIM_IsActiveFlag_ARRM + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_ARRM(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_ARRM) == LPTIM_ISR_ARRM) ? 1UL : 0UL)); +} + +/** + * @brief Clear the external trigger valid edge flag(EXTTRIGCF). + * @rmtoll ICR EXTTRIGCF LL_LPTIM_ClearFlag_EXTTRIG + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFlag_EXTTRIG(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_EXTTRIGCF); +} + +/** + * @brief Inform application whether a valid edge on the selected external trigger input has occurred. + * @rmtoll ISR EXTTRIG LL_LPTIM_IsActiveFlag_EXTTRIG + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_EXTTRIG(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_EXTTRIG) == LPTIM_ISR_EXTTRIG) ? 1UL : 0UL)); +} + +/** + * @brief Clear the compare register update interrupt flag (CMPOKCF). + * @rmtoll ICR CMPOKCF LL_LPTIM_ClearFlag_CMPOK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFlag_CMPOK(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_CMPOKCF); +} + +/** + * @brief Informs application whether the APB bus write operation to the LPTIMx_CMP register has been successfully + completed. If so, a new one can be initiated. + * @rmtoll ISR CMPOK LL_LPTIM_IsActiveFlag_CMPOK + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_CMPOK(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_CMPOK) == LPTIM_ISR_CMPOK) ? 1UL : 0UL)); +} + +/** + * @brief Clear the autoreload register update interrupt flag (ARROKCF). + * @rmtoll ICR ARROKCF LL_LPTIM_ClearFlag_ARROK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFlag_ARROK(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_ARROKCF); +} + +/** + * @brief Informs application whether the APB bus write operation to the LPTIMx_ARR register has been successfully + completed. If so, a new one can be initiated. + * @rmtoll ISR ARROK LL_LPTIM_IsActiveFlag_ARROK + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_ARROK(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_ARROK) == LPTIM_ISR_ARROK) ? 1UL : 0UL)); +} + +/** + * @brief Clear the counter direction change to up interrupt flag (UPCF). + * @rmtoll ICR UPCF LL_LPTIM_ClearFlag_UP + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFlag_UP(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_UPCF); +} + +/** + * @brief Informs the application whether the counter direction has changed from down to up (when the LPTIM instance + operates in encoder mode). + * @rmtoll ISR UP LL_LPTIM_IsActiveFlag_UP + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_UP(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_UP) == LPTIM_ISR_UP) ? 1UL : 0UL)); +} + +/** + * @brief Clear the counter direction change to down interrupt flag (DOWNCF). + * @rmtoll ICR DOWNCF LL_LPTIM_ClearFlag_DOWN + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_ClearFlag_DOWN(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->ICR, LPTIM_ICR_DOWNCF); +} + +/** + * @brief Informs the application whether the counter direction has changed from up to down (when the LPTIM instance + operates in encoder mode). + * @rmtoll ISR DOWN LL_LPTIM_IsActiveFlag_DOWN + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsActiveFlag_DOWN(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->ISR, LPTIM_ISR_DOWN) == LPTIM_ISR_DOWN) ? 1UL : 0UL)); +} + +/** + * @} + */ + +/** @defgroup LPTIM_LL_EF_IT_Management Interrupt Management + * @{ + */ + +/** + * @brief Enable compare match interrupt (CMPMIE). + * @rmtoll IER CMPMIE LL_LPTIM_EnableIT_CMPM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_CMPM(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_CMPMIE); +} + +/** + * @brief Disable compare match interrupt (CMPMIE). + * @rmtoll IER CMPMIE LL_LPTIM_DisableIT_CMPM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_CMPM(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_CMPMIE); +} + +/** + * @brief Indicates whether the compare match interrupt (CMPMIE) is enabled. + * @rmtoll IER CMPMIE LL_LPTIM_IsEnabledIT_CMPM + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_CMPM(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_CMPMIE) == LPTIM_IER_CMPMIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable autoreload match interrupt (ARRMIE). + * @rmtoll IER ARRMIE LL_LPTIM_EnableIT_ARRM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_ARRM(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_ARRMIE); +} + +/** + * @brief Disable autoreload match interrupt (ARRMIE). + * @rmtoll IER ARRMIE LL_LPTIM_DisableIT_ARRM + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_ARRM(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_ARRMIE); +} + +/** + * @brief Indicates whether the autoreload match interrupt (ARRMIE) is enabled. + * @rmtoll IER ARRMIE LL_LPTIM_IsEnabledIT_ARRM + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_ARRM(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_ARRMIE) == LPTIM_IER_ARRMIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable external trigger valid edge interrupt (EXTTRIGIE). + * @rmtoll IER EXTTRIGIE LL_LPTIM_EnableIT_EXTTRIG + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_EXTTRIG(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_EXTTRIGIE); +} + +/** + * @brief Disable external trigger valid edge interrupt (EXTTRIGIE). + * @rmtoll IER EXTTRIGIE LL_LPTIM_DisableIT_EXTTRIG + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_EXTTRIG(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_EXTTRIGIE); +} + +/** + * @brief Indicates external trigger valid edge interrupt (EXTTRIGIE) is enabled. + * @rmtoll IER EXTTRIGIE LL_LPTIM_IsEnabledIT_EXTTRIG + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_EXTTRIG(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_EXTTRIGIE) == LPTIM_IER_EXTTRIGIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable compare register write completed interrupt (CMPOKIE). + * @rmtoll IER CMPOKIE LL_LPTIM_EnableIT_CMPOK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_CMPOK(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_CMPOKIE); +} + +/** + * @brief Disable compare register write completed interrupt (CMPOKIE). + * @rmtoll IER CMPOKIE LL_LPTIM_DisableIT_CMPOK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_CMPOK(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_CMPOKIE); +} + +/** + * @brief Indicates whether the compare register write completed interrupt (CMPOKIE) is enabled. + * @rmtoll IER CMPOKIE LL_LPTIM_IsEnabledIT_CMPOK + * @param LPTIMx Low-Power Timer instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_CMPOK(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_CMPOKIE) == LPTIM_IER_CMPOKIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable autoreload register write completed interrupt (ARROKIE). + * @rmtoll IER ARROKIE LL_LPTIM_EnableIT_ARROK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_ARROK(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_ARROKIE); +} + +/** + * @brief Disable autoreload register write completed interrupt (ARROKIE). + * @rmtoll IER ARROKIE LL_LPTIM_DisableIT_ARROK + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_ARROK(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_ARROKIE); +} + +/** + * @brief Indicates whether the autoreload register write completed interrupt (ARROKIE) is enabled. + * @rmtoll IER ARROKIE LL_LPTIM_IsEnabledIT_ARROK + * @param LPTIMx Low-Power Timer instance + * @retval State of bit(1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_ARROK(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_ARROKIE) == LPTIM_IER_ARROKIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable direction change to up interrupt (UPIE). + * @rmtoll IER UPIE LL_LPTIM_EnableIT_UP + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_UP(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_UPIE); +} + +/** + * @brief Disable direction change to up interrupt (UPIE). + * @rmtoll IER UPIE LL_LPTIM_DisableIT_UP + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_UP(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_UPIE); +} + +/** + * @brief Indicates whether the direction change to up interrupt (UPIE) is enabled. + * @rmtoll IER UPIE LL_LPTIM_IsEnabledIT_UP + * @param LPTIMx Low-Power Timer instance + * @retval State of bit(1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_UP(const LPTIM_TypeDef *LPTIMx) +{ + return (((READ_BIT(LPTIMx->IER, LPTIM_IER_UPIE) == LPTIM_IER_UPIE) ? 1UL : 0UL)); +} + +/** + * @brief Enable direction change to down interrupt (DOWNIE). + * @rmtoll IER DOWNIE LL_LPTIM_EnableIT_DOWN + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_EnableIT_DOWN(LPTIM_TypeDef *LPTIMx) +{ + SET_BIT(LPTIMx->IER, LPTIM_IER_DOWNIE); +} + +/** + * @brief Disable direction change to down interrupt (DOWNIE). + * @rmtoll IER DOWNIE LL_LPTIM_DisableIT_DOWN + * @param LPTIMx Low-Power Timer instance + * @retval None + */ +__STATIC_INLINE void LL_LPTIM_DisableIT_DOWN(LPTIM_TypeDef *LPTIMx) +{ + CLEAR_BIT(LPTIMx->IER, LPTIM_IER_DOWNIE); +} + +/** + * @brief Indicates whether the direction change to down interrupt (DOWNIE) is enabled. + * @rmtoll IER DOWNIE LL_LPTIM_IsEnabledIT_DOWN + * @param LPTIMx Low-Power Timer instance + * @retval State of bit(1 or 0). + */ +__STATIC_INLINE uint32_t LL_LPTIM_IsEnabledIT_DOWN(const LPTIM_TypeDef *LPTIMx) +{ + return ((READ_BIT(LPTIMx->IER, LPTIM_IER_DOWNIE) == LPTIM_IER_DOWNIE) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* LPTIM1 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_LPTIM_H */ diff --git a/libs/hal/stm32f4xx_ll_pwr.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h similarity index 100% rename from libs/hal/stm32f4xx_ll_pwr.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_pwr.h diff --git a/libs/hal/stm32f4xx_ll_rcc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h similarity index 100% rename from libs/hal/stm32f4xx_ll_rcc.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rcc.h diff --git a/libs/hal/stm32f4xx_ll_rng.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h similarity index 100% rename from libs/hal/stm32f4xx_ll_rng.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rng.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h new file mode 100644 index 0000000..bceea23 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_rtc.h @@ -0,0 +1,3663 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_rtc.h + * @author MCD Application Team + * @brief Header file of RTC LL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 STM32F4xx_LL_RTC_H +#define STM32F4xx_LL_RTC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(RTC) + +/** @defgroup RTC_LL RTC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup RTC_LL_Private_Constants RTC Private Constants + * @{ + */ +/* Masks Definition */ +#define RTC_INIT_MASK 0xFFFFFFFFU +#define RTC_RSF_MASK ((uint32_t)~(RTC_ISR_INIT | RTC_ISR_RSF)) + +/* Write protection defines */ +#define RTC_WRITE_PROTECTION_DISABLE ((uint8_t)0xFFU) +#define RTC_WRITE_PROTECTION_ENABLE_1 ((uint8_t)0xCAU) +#define RTC_WRITE_PROTECTION_ENABLE_2 ((uint8_t)0x53U) + +/* Defines used to combine date & time */ +#define RTC_OFFSET_WEEKDAY 24U +#define RTC_OFFSET_DAY 16U +#define RTC_OFFSET_MONTH 8U +#define RTC_OFFSET_HOUR 16U +#define RTC_OFFSET_MINUTE 8U + +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RTC_LL_Private_Macros RTC Private Macros + * @{ + */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RTC_LL_ES_INIT RTC Exported Init structure + * @{ + */ + +/** + * @brief RTC Init structures definition + */ +typedef struct +{ + uint32_t HourFormat; /*!< Specifies the RTC Hours Format. + This parameter can be a value of @ref RTC_LL_EC_HOURFORMAT + + This feature can be modified afterwards using unitary function + @ref LL_RTC_SetHourFormat(). */ + + uint32_t AsynchPrescaler; /*!< Specifies the RTC Asynchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7F + + This feature can be modified afterwards using unitary function + @ref LL_RTC_SetAsynchPrescaler(). */ + + uint32_t SynchPrescaler; /*!< Specifies the RTC Synchronous Predivider value. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0x7FFF + + This feature can be modified afterwards using unitary function + @ref LL_RTC_SetSynchPrescaler(). */ +} LL_RTC_InitTypeDef; + +/** + * @brief RTC Time structure definition + */ +typedef struct +{ + uint32_t TimeFormat; /*!< Specifies the RTC AM/PM Time. + This parameter can be a value of @ref RTC_LL_EC_TIME_FORMAT + + This feature can be modified afterwards using unitary function @ref LL_RTC_TIME_SetFormat(). */ + + uint8_t Hours; /*!< Specifies the RTC Time Hours. + This parameter must be a number between Min_Data = 0 and Max_Data = 12 if the @ref LL_RTC_TIME_FORMAT_PM is selected. + This parameter must be a number between Min_Data = 0 and Max_Data = 23 if the @ref LL_RTC_TIME_FORMAT_AM_OR_24 is selected. + + This feature can be modified afterwards using unitary function @ref LL_RTC_TIME_SetHour(). */ + + uint8_t Minutes; /*!< Specifies the RTC Time Minutes. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 + + This feature can be modified afterwards using unitary function @ref LL_RTC_TIME_SetMinute(). */ + + uint8_t Seconds; /*!< Specifies the RTC Time Seconds. + This parameter must be a number between Min_Data = 0 and Max_Data = 59 + + This feature can be modified afterwards using unitary function @ref LL_RTC_TIME_SetSecond(). */ +} LL_RTC_TimeTypeDef; + +/** + * @brief RTC Date structure definition + */ +typedef struct +{ + uint8_t WeekDay; /*!< Specifies the RTC Date WeekDay. + This parameter can be a value of @ref RTC_LL_EC_WEEKDAY + + This feature can be modified afterwards using unitary function @ref LL_RTC_DATE_SetWeekDay(). */ + + uint8_t Month; /*!< Specifies the RTC Date Month. + This parameter can be a value of @ref RTC_LL_EC_MONTH + + This feature can be modified afterwards using unitary function @ref LL_RTC_DATE_SetMonth(). */ + + uint8_t Day; /*!< Specifies the RTC Date Day. + This parameter must be a number between Min_Data = 1 and Max_Data = 31 + + This feature can be modified afterwards using unitary function @ref LL_RTC_DATE_SetDay(). */ + + uint8_t Year; /*!< Specifies the RTC Date Year. + This parameter must be a number between Min_Data = 0 and Max_Data = 99 + + This feature can be modified afterwards using unitary function @ref LL_RTC_DATE_SetYear(). */ +} LL_RTC_DateTypeDef; + +/** + * @brief RTC Alarm structure definition + */ +typedef struct +{ + LL_RTC_TimeTypeDef AlarmTime; /*!< Specifies the RTC Alarm Time members. */ + + uint32_t AlarmMask; /*!< Specifies the RTC Alarm Masks. + This parameter can be a value of @ref RTC_LL_EC_ALMA_MASK for ALARM A or @ref RTC_LL_EC_ALMB_MASK for ALARM B. + + This feature can be modified afterwards using unitary function @ref LL_RTC_ALMA_SetMask() for ALARM A + or @ref LL_RTC_ALMB_SetMask() for ALARM B. + */ + + uint32_t AlarmDateWeekDaySel; /*!< Specifies the RTC Alarm is on day or WeekDay. + This parameter can be a value of @ref RTC_LL_EC_ALMA_WEEKDAY_SELECTION for ALARM A or @ref RTC_LL_EC_ALMB_WEEKDAY_SELECTION for ALARM B + + This feature can be modified afterwards using unitary function @ref LL_RTC_ALMA_EnableWeekday() or @ref LL_RTC_ALMA_DisableWeekday() + for ALARM A or @ref LL_RTC_ALMB_EnableWeekday() or @ref LL_RTC_ALMB_DisableWeekday() for ALARM B + */ + + uint8_t AlarmDateWeekDay; /*!< Specifies the RTC Alarm Day/WeekDay. + If AlarmDateWeekDaySel set to day, this parameter must be a number between Min_Data = 1 and Max_Data = 31. + + This feature can be modified afterwards using unitary function @ref LL_RTC_ALMA_SetDay() + for ALARM A or @ref LL_RTC_ALMB_SetDay() for ALARM B. + + If AlarmDateWeekDaySel set to Weekday, this parameter can be a value of @ref RTC_LL_EC_WEEKDAY. + + This feature can be modified afterwards using unitary function @ref LL_RTC_ALMA_SetWeekDay() + for ALARM A or @ref LL_RTC_ALMB_SetWeekDay() for ALARM B. + */ +} LL_RTC_AlarmTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup RTC_LL_Exported_Constants RTC Exported Constants + * @{ + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RTC_LL_EC_FORMAT FORMAT + * @{ + */ +#define LL_RTC_FORMAT_BIN 0x00000000U /*!< Binary data format */ +#define LL_RTC_FORMAT_BCD 0x00000001U /*!< BCD data format */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMA_WEEKDAY_SELECTION RTC Alarm A Date WeekDay + * @{ + */ +#define LL_RTC_ALMA_DATEWEEKDAYSEL_DATE 0x00000000U /*!< Alarm A Date is selected */ +#define LL_RTC_ALMA_DATEWEEKDAYSEL_WEEKDAY RTC_ALRMAR_WDSEL /*!< Alarm A WeekDay is selected */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMB_WEEKDAY_SELECTION RTC Alarm B Date WeekDay + * @{ + */ +#define LL_RTC_ALMB_DATEWEEKDAYSEL_DATE 0x00000000U /*!< Alarm B Date is selected */ +#define LL_RTC_ALMB_DATEWEEKDAYSEL_WEEKDAY RTC_ALRMBR_WDSEL /*!< Alarm B WeekDay is selected */ +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + +/** @defgroup RTC_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_RTC_ReadReg function + * @{ + */ +#define LL_RTC_ISR_RECALPF RTC_ISR_RECALPF +#if defined(RTC_TAMPER2_SUPPORT) +#define LL_RTC_ISR_TAMP2F RTC_ISR_TAMP2F +#endif /* RTC_TAMPER2_SUPPORT */ +#define LL_RTC_ISR_TAMP1F RTC_ISR_TAMP1F +#define LL_RTC_ISR_TSOVF RTC_ISR_TSOVF +#define LL_RTC_ISR_TSF RTC_ISR_TSF +#define LL_RTC_ISR_WUTF RTC_ISR_WUTF +#define LL_RTC_ISR_ALRBF RTC_ISR_ALRBF +#define LL_RTC_ISR_ALRAF RTC_ISR_ALRAF +#define LL_RTC_ISR_INITF RTC_ISR_INITF +#define LL_RTC_ISR_RSF RTC_ISR_RSF +#define LL_RTC_ISR_INITS RTC_ISR_INITS +#define LL_RTC_ISR_SHPF RTC_ISR_SHPF +#define LL_RTC_ISR_WUTWF RTC_ISR_WUTWF +#define LL_RTC_ISR_ALRBWF RTC_ISR_ALRBWF +#define LL_RTC_ISR_ALRAWF RTC_ISR_ALRAWF +/** + * @} + */ + +/** @defgroup RTC_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_RTC_ReadReg and LL_RTC_WriteReg functions + * @{ + */ +#define LL_RTC_CR_TSIE RTC_CR_TSIE +#define LL_RTC_CR_WUTIE RTC_CR_WUTIE +#define LL_RTC_CR_ALRBIE RTC_CR_ALRBIE +#define LL_RTC_CR_ALRAIE RTC_CR_ALRAIE +#define LL_RTC_TAFCR_TAMPIE RTC_TAFCR_TAMPIE +/** + * @} + */ + +/** @defgroup RTC_LL_EC_WEEKDAY WEEK DAY + * @{ + */ +#define LL_RTC_WEEKDAY_MONDAY ((uint8_t)0x01U) /*!< Monday */ +#define LL_RTC_WEEKDAY_TUESDAY ((uint8_t)0x02U) /*!< Tuesday */ +#define LL_RTC_WEEKDAY_WEDNESDAY ((uint8_t)0x03U) /*!< Wednesday */ +#define LL_RTC_WEEKDAY_THURSDAY ((uint8_t)0x04U) /*!< Thrusday */ +#define LL_RTC_WEEKDAY_FRIDAY ((uint8_t)0x05U) /*!< Friday */ +#define LL_RTC_WEEKDAY_SATURDAY ((uint8_t)0x06U) /*!< Saturday */ +#define LL_RTC_WEEKDAY_SUNDAY ((uint8_t)0x07U) /*!< Sunday */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_MONTH MONTH + * @{ + */ +#define LL_RTC_MONTH_JANUARY ((uint8_t)0x01U) /*!< January */ +#define LL_RTC_MONTH_FEBRUARY ((uint8_t)0x02U) /*!< February */ +#define LL_RTC_MONTH_MARCH ((uint8_t)0x03U) /*!< March */ +#define LL_RTC_MONTH_APRIL ((uint8_t)0x04U) /*!< April */ +#define LL_RTC_MONTH_MAY ((uint8_t)0x05U) /*!< May */ +#define LL_RTC_MONTH_JUNE ((uint8_t)0x06U) /*!< June */ +#define LL_RTC_MONTH_JULY ((uint8_t)0x07U) /*!< July */ +#define LL_RTC_MONTH_AUGUST ((uint8_t)0x08U) /*!< August */ +#define LL_RTC_MONTH_SEPTEMBER ((uint8_t)0x09U) /*!< September */ +#define LL_RTC_MONTH_OCTOBER ((uint8_t)0x10U) /*!< October */ +#define LL_RTC_MONTH_NOVEMBER ((uint8_t)0x11U) /*!< November */ +#define LL_RTC_MONTH_DECEMBER ((uint8_t)0x12U) /*!< December */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_HOURFORMAT HOUR FORMAT + * @{ + */ +#define LL_RTC_HOURFORMAT_24HOUR 0x00000000U /*!< 24 hour/day format */ +#define LL_RTC_HOURFORMAT_AMPM RTC_CR_FMT /*!< AM/PM hour format */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALARMOUT ALARM OUTPUT + * @{ + */ +#define LL_RTC_ALARMOUT_DISABLE 0x00000000U /*!< Output disabled */ +#define LL_RTC_ALARMOUT_ALMA RTC_CR_OSEL_0 /*!< Alarm A output enabled */ +#define LL_RTC_ALARMOUT_ALMB RTC_CR_OSEL_1 /*!< Alarm B output enabled */ +#define LL_RTC_ALARMOUT_WAKEUP RTC_CR_OSEL /*!< Wakeup output enabled */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALARM_OUTPUTTYPE ALARM OUTPUT TYPE + * @{ + */ +#define LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN 0x00000000U /*!< RTC_ALARM, when mapped on PC13, is open-drain output */ +#define LL_RTC_ALARM_OUTPUTTYPE_PUSHPULL RTC_TAFCR_ALARMOUTTYPE /*!< RTC_ALARM, when mapped on PC13, is push-pull output */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_OUTPUTPOLARITY_PIN OUTPUT POLARITY PIN + * @{ + */ +#define LL_RTC_OUTPUTPOLARITY_PIN_HIGH 0x00000000U /*!< Pin is high when ALRAF/ALRBF/WUTF is asserted (depending on OSEL)*/ +#define LL_RTC_OUTPUTPOLARITY_PIN_LOW RTC_CR_POL /*!< Pin is low when ALRAF/ALRBF/WUTF is asserted (depending on OSEL) */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TIME_FORMAT TIME FORMAT + * @{ + */ +#define LL_RTC_TIME_FORMAT_AM_OR_24 0x00000000U /*!< AM or 24-hour format */ +#define LL_RTC_TIME_FORMAT_PM RTC_TR_PM /*!< PM */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_SHIFT_SECOND SHIFT SECOND + * @{ + */ +#define LL_RTC_SHIFT_SECOND_DELAY 0x00000000U /* Delay (seconds) = SUBFS / (PREDIV_S + 1) */ +#define LL_RTC_SHIFT_SECOND_ADVANCE RTC_SHIFTR_ADD1S /* Advance (seconds) = (1 - (SUBFS / (PREDIV_S + 1))) */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMA_MASK ALARMA MASK + * @{ + */ +#define LL_RTC_ALMA_MASK_NONE 0x00000000U /*!< No masks applied on Alarm A*/ +#define LL_RTC_ALMA_MASK_DATEWEEKDAY RTC_ALRMAR_MSK4 /*!< Date/day do not care in Alarm A comparison */ +#define LL_RTC_ALMA_MASK_HOURS RTC_ALRMAR_MSK3 /*!< Hours do not care in Alarm A comparison */ +#define LL_RTC_ALMA_MASK_MINUTES RTC_ALRMAR_MSK2 /*!< Minutes do not care in Alarm A comparison */ +#define LL_RTC_ALMA_MASK_SECONDS RTC_ALRMAR_MSK1 /*!< Seconds do not care in Alarm A comparison */ +#define LL_RTC_ALMA_MASK_ALL (RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1) /*!< Masks all */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMA_TIME_FORMAT ALARMA TIME FORMAT + * @{ + */ +#define LL_RTC_ALMA_TIME_FORMAT_AM 0x00000000U /*!< AM or 24-hour format */ +#define LL_RTC_ALMA_TIME_FORMAT_PM RTC_ALRMAR_PM /*!< PM */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMB_MASK ALARMB MASK + * @{ + */ +#define LL_RTC_ALMB_MASK_NONE 0x00000000U /*!< No masks applied on Alarm B */ +#define LL_RTC_ALMB_MASK_DATEWEEKDAY RTC_ALRMBR_MSK4 /*!< Date/day do not care in Alarm B comparison */ +#define LL_RTC_ALMB_MASK_HOURS RTC_ALRMBR_MSK3 /*!< Hours do not care in Alarm B comparison */ +#define LL_RTC_ALMB_MASK_MINUTES RTC_ALRMBR_MSK2 /*!< Minutes do not care in Alarm B comparison */ +#define LL_RTC_ALMB_MASK_SECONDS RTC_ALRMBR_MSK1 /*!< Seconds do not care in Alarm B comparison */ +#define LL_RTC_ALMB_MASK_ALL (RTC_ALRMBR_MSK4 | RTC_ALRMBR_MSK3 | RTC_ALRMBR_MSK2 | RTC_ALRMBR_MSK1) /*!< Masks all */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_ALMB_TIME_FORMAT ALARMB TIME FORMAT + * @{ + */ +#define LL_RTC_ALMB_TIME_FORMAT_AM 0x00000000U /*!< AM or 24-hour format */ +#define LL_RTC_ALMB_TIME_FORMAT_PM RTC_ALRMBR_PM /*!< PM */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TIMESTAMP_EDGE TIMESTAMP EDGE + * @{ + */ +#define LL_RTC_TIMESTAMP_EDGE_RISING 0x00000000U /*!< RTC_TS input rising edge generates a time-stamp event */ +#define LL_RTC_TIMESTAMP_EDGE_FALLING RTC_CR_TSEDGE /*!< RTC_TS input falling edge generates a time-stamp even */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TS_TIME_FORMAT TIMESTAMP TIME FORMAT + * @{ + */ +#define LL_RTC_TS_TIME_FORMAT_AM 0x00000000U /*!< AM or 24-hour format */ +#define LL_RTC_TS_TIME_FORMAT_PM RTC_TSTR_PM /*!< PM */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMPER TAMPER + * @{ + */ +#define LL_RTC_TAMPER_1 RTC_TAFCR_TAMP1E /*!< RTC_TAMP1 input detection */ +#if defined(RTC_TAMPER2_SUPPORT) +#define LL_RTC_TAMPER_2 RTC_TAFCR_TAMP2E /*!< RTC_TAMP2 input detection */ +#endif /* RTC_TAMPER2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMPER_DURATION TAMPER DURATION + * @{ + */ +#define LL_RTC_TAMPER_DURATION_1RTCCLK 0x00000000U /*!< Tamper pins are pre-charged before sampling during 1 RTCCLK cycle */ +#define LL_RTC_TAMPER_DURATION_2RTCCLK RTC_TAFCR_TAMPPRCH_0 /*!< Tamper pins are pre-charged before sampling during 2 RTCCLK cycles */ +#define LL_RTC_TAMPER_DURATION_4RTCCLK RTC_TAFCR_TAMPPRCH_1 /*!< Tamper pins are pre-charged before sampling during 4 RTCCLK cycles */ +#define LL_RTC_TAMPER_DURATION_8RTCCLK RTC_TAFCR_TAMPPRCH /*!< Tamper pins are pre-charged before sampling during 8 RTCCLK cycles */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMPER_FILTER TAMPER FILTER + * @{ + */ +#define LL_RTC_TAMPER_FILTER_DISABLE 0x00000000U /*!< Tamper filter is disabled */ +#define LL_RTC_TAMPER_FILTER_2SAMPLE RTC_TAFCR_TAMPFLT_0 /*!< Tamper is activated after 2 consecutive samples at the active level */ +#define LL_RTC_TAMPER_FILTER_4SAMPLE RTC_TAFCR_TAMPFLT_1 /*!< Tamper is activated after 4 consecutive samples at the active level */ +#define LL_RTC_TAMPER_FILTER_8SAMPLE RTC_TAFCR_TAMPFLT /*!< Tamper is activated after 8 consecutive samples at the active level. */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMPER_SAMPLFREQDIV TAMPER SAMPLING FREQUENCY DIVIDER + * @{ + */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_32768 0x00000000U /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 32768 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_16384 RTC_TAFCR_TAMPFREQ_0 /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 16384 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_8192 RTC_TAFCR_TAMPFREQ_1 /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 8192 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_4096 (RTC_TAFCR_TAMPFREQ_1 | RTC_TAFCR_TAMPFREQ_0) /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 4096 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_2048 RTC_TAFCR_TAMPFREQ_2 /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 2048 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_1024 (RTC_TAFCR_TAMPFREQ_2 | RTC_TAFCR_TAMPFREQ_0) /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 1024 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_512 (RTC_TAFCR_TAMPFREQ_2 | RTC_TAFCR_TAMPFREQ_1) /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 512 */ +#define LL_RTC_TAMPER_SAMPLFREQDIV_256 RTC_TAFCR_TAMPFREQ /*!< Each of the tamper inputs are sampled with a frequency = RTCCLK / 256 */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMPER_ACTIVELEVEL TAMPER ACTIVE LEVEL + * @{ + */ +#define LL_RTC_TAMPER_ACTIVELEVEL_TAMP1 RTC_TAFCR_TAMP1TRG /*!< RTC_TAMP1 input falling edge (if TAMPFLT = 00) or staying high (if TAMPFLT != 00) triggers a tamper detection event */ +#if defined(RTC_TAMPER2_SUPPORT) +#define LL_RTC_TAMPER_ACTIVELEVEL_TAMP2 RTC_TAFCR_TAMP2TRG /*!< RTC_TAMP2 input falling edge (if TAMPFLT = 00) or staying high (if TAMPFLT != 00) triggers a tamper detection event */ +#endif /* RTC_TAMPER2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_WAKEUPCLOCK_DIV WAKEUP CLOCK DIV + * @{ + */ +#define LL_RTC_WAKEUPCLOCK_DIV_16 0x00000000U /*!< RTC/16 clock is selected */ +#define LL_RTC_WAKEUPCLOCK_DIV_8 (RTC_CR_WUCKSEL_0) /*!< RTC/8 clock is selected */ +#define LL_RTC_WAKEUPCLOCK_DIV_4 (RTC_CR_WUCKSEL_1) /*!< RTC/4 clock is selected */ +#define LL_RTC_WAKEUPCLOCK_DIV_2 (RTC_CR_WUCKSEL_1 | RTC_CR_WUCKSEL_0) /*!< RTC/2 clock is selected */ +#define LL_RTC_WAKEUPCLOCK_CKSPRE (RTC_CR_WUCKSEL_2) /*!< ck_spre (usually 1 Hz) clock is selected */ +#define LL_RTC_WAKEUPCLOCK_CKSPRE_WUT (RTC_CR_WUCKSEL_2 | RTC_CR_WUCKSEL_1) /*!< ck_spre (usually 1 Hz) clock is selected and 2exp16 is added to the WUT counter value*/ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_BKP BACKUP + * @{ + */ +#define LL_RTC_BKP_DR0 0x00000000U +#define LL_RTC_BKP_DR1 0x00000001U +#define LL_RTC_BKP_DR2 0x00000002U +#define LL_RTC_BKP_DR3 0x00000003U +#define LL_RTC_BKP_DR4 0x00000004U +#define LL_RTC_BKP_DR5 0x00000005U +#define LL_RTC_BKP_DR6 0x00000006U +#define LL_RTC_BKP_DR7 0x00000007U +#define LL_RTC_BKP_DR8 0x00000008U +#define LL_RTC_BKP_DR9 0x00000009U +#define LL_RTC_BKP_DR10 0x0000000AU +#define LL_RTC_BKP_DR11 0x0000000BU +#define LL_RTC_BKP_DR12 0x0000000CU +#define LL_RTC_BKP_DR13 0x0000000DU +#define LL_RTC_BKP_DR14 0x0000000EU +#define LL_RTC_BKP_DR15 0x0000000FU +#define LL_RTC_BKP_DR16 0x00000010U +#define LL_RTC_BKP_DR17 0x00000011U +#define LL_RTC_BKP_DR18 0x00000012U +#define LL_RTC_BKP_DR19 0x00000013U +/** + * @} + */ + +/** @defgroup RTC_LL_EC_CALIB_OUTPUT Calibration output + * @{ + */ +#define LL_RTC_CALIB_OUTPUT_NONE 0x00000000U /*!< Calibration output disabled */ +#define LL_RTC_CALIB_OUTPUT_1HZ (RTC_CR_COE | RTC_CR_COSEL) /*!< Calibration output is 1 Hz */ +#define LL_RTC_CALIB_OUTPUT_512HZ (RTC_CR_COE) /*!< Calibration output is 512 Hz */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_CALIB_SIGN Coarse digital calibration sign + * @{ + */ +#define LL_RTC_CALIB_SIGN_POSITIVE 0x00000000U /*!< Positive calibration: calendar update frequency is increased */ +#define LL_RTC_CALIB_SIGN_NEGATIVE RTC_CALIBR_DCS /*!< Negative calibration: calendar update frequency is decreased */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_CALIB_INSERTPULSE Calibration pulse insertion + * @{ + */ +#define LL_RTC_CALIB_INSERTPULSE_NONE 0x00000000U /*!< No RTCCLK pulses are added */ +#define LL_RTC_CALIB_INSERTPULSE_SET RTC_CALR_CALP /*!< One RTCCLK pulse is effectively inserted every 2exp11 pulses (frequency increased by 488.5 ppm) */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_CALIB_PERIOD Calibration period + * @{ + */ +#define LL_RTC_CALIB_PERIOD_32SEC 0x00000000U /*!< Use a 32-second calibration cycle period */ +#define LL_RTC_CALIB_PERIOD_16SEC RTC_CALR_CALW16 /*!< Use a 16-second calibration cycle period */ +#define LL_RTC_CALIB_PERIOD_8SEC RTC_CALR_CALW8 /*!< Use a 8-second calibration cycle period */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TSINSEL TIMESTAMP mapping + * @{ + */ +#define LL_RTC_TimeStampPin_Default 0x00000000U /*!< Use RTC_AF1 as TIMESTAMP */ +#if defined(RTC_AF2_SUPPORT) +#define LL_RTC_TimeStampPin_Pos1 RTC_TAFCR_TSINSEL /*!< Use RTC_AF2 as TIMESTAMP */ +#endif /* RTC_AF2_SUPPORT */ +/** + * @} + */ + +/** @defgroup RTC_LL_EC_TAMP1INSEL TAMPER1 mapping + * @{ + */ +#define LL_RTC_TamperPin_Default 0x00000000U /*!< Use RTC_AF1 as TAMPER1 */ +#if defined(RTC_AF2_SUPPORT) +#define LL_RTC_TamperPin_Pos1 RTC_TAFCR_TAMP1INSEL /*!< Use RTC_AF2 as TAMPER1 */ +#endif /* RTC_AF2_SUPPORT */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup RTC_LL_Exported_Macros RTC Exported Macros + * @{ + */ + +/** @defgroup RTC_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in RTC register + * @param __INSTANCE__ RTC Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_RTC_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in RTC register + * @param __INSTANCE__ RTC Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_RTC_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** @defgroup RTC_LL_EM_Convert Convert helper Macros + * @{ + */ + +/** + * @brief Helper macro to convert a value from 2 digit decimal format to BCD format + * @param __VALUE__ Byte to be converted + * @retval Converted byte + */ +#define __LL_RTC_CONVERT_BIN2BCD(__VALUE__) (uint8_t)((((__VALUE__) / 10U) << 4U) | ((__VALUE__) % 10U)) + +/** + * @brief Helper macro to convert a value from BCD format to 2 digit decimal format + * @param __VALUE__ BCD value to be converted + * @retval Converted byte + */ +#define __LL_RTC_CONVERT_BCD2BIN(__VALUE__) (uint8_t)(((uint8_t)((__VALUE__) & (uint8_t)0xF0U) >> (uint8_t)0x4U) * 10U + ((__VALUE__) & (uint8_t)0x0FU)) + +/** + * @} + */ + +/** @defgroup RTC_LL_EM_Date Date helper Macros + * @{ + */ + +/** + * @brief Helper macro to retrieve weekday. + * @param __RTC_DATE__ Date returned by @ref LL_RTC_DATE_Get function. + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + */ +#define __LL_RTC_GET_WEEKDAY(__RTC_DATE__) (((__RTC_DATE__) >> RTC_OFFSET_WEEKDAY) & 0x000000FFU) + +/** + * @brief Helper macro to retrieve Year in BCD format + * @param __RTC_DATE__ Value returned by @ref LL_RTC_DATE_Get + * @retval Year in BCD format (0x00 . . . 0x99) + */ +#define __LL_RTC_GET_YEAR(__RTC_DATE__) ((__RTC_DATE__) & 0x000000FFU) + +/** + * @brief Helper macro to retrieve Month in BCD format + * @param __RTC_DATE__ Value returned by @ref LL_RTC_DATE_Get + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_MONTH_JANUARY + * @arg @ref LL_RTC_MONTH_FEBRUARY + * @arg @ref LL_RTC_MONTH_MARCH + * @arg @ref LL_RTC_MONTH_APRIL + * @arg @ref LL_RTC_MONTH_MAY + * @arg @ref LL_RTC_MONTH_JUNE + * @arg @ref LL_RTC_MONTH_JULY + * @arg @ref LL_RTC_MONTH_AUGUST + * @arg @ref LL_RTC_MONTH_SEPTEMBER + * @arg @ref LL_RTC_MONTH_OCTOBER + * @arg @ref LL_RTC_MONTH_NOVEMBER + * @arg @ref LL_RTC_MONTH_DECEMBER + */ +#define __LL_RTC_GET_MONTH(__RTC_DATE__) (((__RTC_DATE__) >>RTC_OFFSET_MONTH) & 0x000000FFU) + +/** + * @brief Helper macro to retrieve Day in BCD format + * @param __RTC_DATE__ Value returned by @ref LL_RTC_DATE_Get + * @retval Day in BCD format (0x01 . . . 0x31) + */ +#define __LL_RTC_GET_DAY(__RTC_DATE__) (((__RTC_DATE__) >>RTC_OFFSET_DAY) & 0x000000FFU) + +/** + * @} + */ + +/** @defgroup RTC_LL_EM_Time Time helper Macros + * @{ + */ + +/** + * @brief Helper macro to retrieve hour in BCD format + * @param __RTC_TIME__ RTC time returned by @ref LL_RTC_TIME_Get function + * @retval Hours in BCD format (0x01. . .0x12 or between Min_Data=0x00 and Max_Data=0x23) + */ +#define __LL_RTC_GET_HOUR(__RTC_TIME__) (((__RTC_TIME__) >> RTC_OFFSET_HOUR) & 0x000000FFU) + +/** + * @brief Helper macro to retrieve minute in BCD format + * @param __RTC_TIME__ RTC time returned by @ref LL_RTC_TIME_Get function + * @retval Minutes in BCD format (0x00. . .0x59) + */ +#define __LL_RTC_GET_MINUTE(__RTC_TIME__) (((__RTC_TIME__) >> RTC_OFFSET_MINUTE) & 0x000000FFU) + +/** + * @brief Helper macro to retrieve second in BCD format + * @param __RTC_TIME__ RTC time returned by @ref LL_RTC_TIME_Get function + * @retval Seconds in format (0x00. . .0x59) + */ +#define __LL_RTC_GET_SECOND(__RTC_TIME__) ((__RTC_TIME__) & 0x000000FFU) + +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup RTC_LL_Exported_Functions RTC Exported Functions + * @{ + */ + +/** @defgroup RTC_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Set Hours format (24 hour/day or AM/PM hour format) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CR FMT LL_RTC_SetHourFormat + * @param RTCx RTC Instance + * @param HourFormat This parameter can be one of the following values: + * @arg @ref LL_RTC_HOURFORMAT_24HOUR + * @arg @ref LL_RTC_HOURFORMAT_AMPM + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetHourFormat(RTC_TypeDef *RTCx, uint32_t HourFormat) +{ + MODIFY_REG(RTCx->CR, RTC_CR_FMT, HourFormat); +} + +/** + * @brief Get Hours format (24 hour/day or AM/PM hour format) + * @rmtoll CR FMT LL_RTC_GetHourFormat + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_HOURFORMAT_24HOUR + * @arg @ref LL_RTC_HOURFORMAT_AMPM + */ +__STATIC_INLINE uint32_t LL_RTC_GetHourFormat(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_FMT)); +} + +/** + * @brief Select the flag to be routed to RTC_ALARM output + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR OSEL LL_RTC_SetAlarmOutEvent + * @param RTCx RTC Instance + * @param AlarmOutput This parameter can be one of the following values: + * @arg @ref LL_RTC_ALARMOUT_DISABLE + * @arg @ref LL_RTC_ALARMOUT_ALMA + * @arg @ref LL_RTC_ALARMOUT_ALMB + * @arg @ref LL_RTC_ALARMOUT_WAKEUP + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetAlarmOutEvent(RTC_TypeDef *RTCx, uint32_t AlarmOutput) +{ + MODIFY_REG(RTCx->CR, RTC_CR_OSEL, AlarmOutput); +} + +/** + * @brief Get the flag to be routed to RTC_ALARM output + * @rmtoll CR OSEL LL_RTC_GetAlarmOutEvent + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_ALARMOUT_DISABLE + * @arg @ref LL_RTC_ALARMOUT_ALMA + * @arg @ref LL_RTC_ALARMOUT_ALMB + * @arg @ref LL_RTC_ALARMOUT_WAKEUP + */ +__STATIC_INLINE uint32_t LL_RTC_GetAlarmOutEvent(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_OSEL)); +} + +/** + * @brief Set RTC_ALARM output type (ALARM in push-pull or open-drain output) + * @note Used only when RTC_ALARM is mapped on PC13 + * @rmtoll TAFCR ALARMOUTTYPE LL_RTC_SetAlarmOutputType + * @param RTCx RTC Instance + * @param Output This parameter can be one of the following values: + * @arg @ref LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN + * @arg @ref LL_RTC_ALARM_OUTPUTTYPE_PUSHPULL + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetAlarmOutputType(RTC_TypeDef *RTCx, uint32_t Output) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_ALARMOUTTYPE, Output); +} + +/** + * @brief Get RTC_ALARM output type (ALARM in push-pull or open-drain output) + * @note used only when RTC_ALARM is mapped on PC13 + * @rmtoll TAFCR ALARMOUTTYPE LL_RTC_GetAlarmOutputType + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN + * @arg @ref LL_RTC_ALARM_OUTPUTTYPE_PUSHPULL + */ +__STATIC_INLINE uint32_t LL_RTC_GetAlarmOutputType(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_ALARMOUTTYPE)); +} + +/** + * @brief Enable initialization mode + * @note Initialization mode is used to program time and date register (RTC_TR and RTC_DR) + * and prescaler register (RTC_PRER). + * Counters are stopped and start counting from the new value when INIT is reset. + * @rmtoll ISR INIT LL_RTC_EnableInitMode + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableInitMode(RTC_TypeDef *RTCx) +{ + /* Set the Initialization mode */ + WRITE_REG(RTCx->ISR, RTC_INIT_MASK); +} + +/** + * @brief Disable initialization mode (Free running mode) + * @rmtoll ISR INIT LL_RTC_DisableInitMode + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableInitMode(RTC_TypeDef *RTCx) +{ + /* Exit Initialization mode */ + WRITE_REG(RTCx->ISR, (uint32_t)~RTC_ISR_INIT); +} + +/** + * @brief Set Output polarity (pin is low when ALRAF/ALRBF/WUTF is asserted) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR POL LL_RTC_SetOutputPolarity + * @param RTCx RTC Instance + * @param Polarity This parameter can be one of the following values: + * @arg @ref LL_RTC_OUTPUTPOLARITY_PIN_HIGH + * @arg @ref LL_RTC_OUTPUTPOLARITY_PIN_LOW + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetOutputPolarity(RTC_TypeDef *RTCx, uint32_t Polarity) +{ + MODIFY_REG(RTCx->CR, RTC_CR_POL, Polarity); +} + +/** + * @brief Get Output polarity + * @rmtoll CR POL LL_RTC_GetOutputPolarity + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_OUTPUTPOLARITY_PIN_HIGH + * @arg @ref LL_RTC_OUTPUTPOLARITY_PIN_LOW + */ +__STATIC_INLINE uint32_t LL_RTC_GetOutputPolarity(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_POL)); +} + +/** + * @brief Enable Bypass the shadow registers + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR BYPSHAD LL_RTC_EnableShadowRegBypass + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableShadowRegBypass(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_BYPSHAD); +} + +/** + * @brief Disable Bypass the shadow registers + * @rmtoll CR BYPSHAD LL_RTC_DisableShadowRegBypass + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableShadowRegBypass(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_BYPSHAD); +} + +/** + * @brief Check if Shadow registers bypass is enabled or not. + * @rmtoll CR BYPSHAD LL_RTC_IsShadowRegBypassEnabled + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsShadowRegBypassEnabled(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_BYPSHAD) == (RTC_CR_BYPSHAD)) ? 1UL : 0UL); +} + +/** + * @brief Enable RTC_REFIN reference clock detection (50 or 60 Hz) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CR REFCKON LL_RTC_EnableRefClock + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableRefClock(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_REFCKON); +} + +/** + * @brief Disable RTC_REFIN reference clock detection (50 or 60 Hz) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CR REFCKON LL_RTC_DisableRefClock + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableRefClock(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_REFCKON); +} + +/** + * @brief Set Asynchronous prescaler factor + * @rmtoll PRER PREDIV_A LL_RTC_SetAsynchPrescaler + * @param RTCx RTC Instance + * @param AsynchPrescaler Value between Min_Data = 0 and Max_Data = 0x7F + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetAsynchPrescaler(RTC_TypeDef *RTCx, uint32_t AsynchPrescaler) +{ + MODIFY_REG(RTCx->PRER, RTC_PRER_PREDIV_A, AsynchPrescaler << RTC_PRER_PREDIV_A_Pos); +} + +/** + * @brief Set Synchronous prescaler factor + * @rmtoll PRER PREDIV_S LL_RTC_SetSynchPrescaler + * @param RTCx RTC Instance + * @param SynchPrescaler Value between Min_Data = 0 and Max_Data = 0x7FFF + * @retval None + */ +__STATIC_INLINE void LL_RTC_SetSynchPrescaler(RTC_TypeDef *RTCx, uint32_t SynchPrescaler) +{ + MODIFY_REG(RTCx->PRER, RTC_PRER_PREDIV_S, SynchPrescaler); +} + +/** + * @brief Get Asynchronous prescaler factor + * @rmtoll PRER PREDIV_A LL_RTC_GetAsynchPrescaler + * @param RTCx RTC Instance + * @retval Value between Min_Data = 0 and Max_Data = 0x7F + */ +__STATIC_INLINE uint32_t LL_RTC_GetAsynchPrescaler(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->PRER, RTC_PRER_PREDIV_A) >> RTC_PRER_PREDIV_A_Pos); +} + +/** + * @brief Get Synchronous prescaler factor + * @rmtoll PRER PREDIV_S LL_RTC_GetSynchPrescaler + * @param RTCx RTC Instance + * @retval Value between Min_Data = 0 and Max_Data = 0x7FFF + */ +__STATIC_INLINE uint32_t LL_RTC_GetSynchPrescaler(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->PRER, RTC_PRER_PREDIV_S)); +} + +/** + * @brief Enable the write protection for RTC registers. + * @rmtoll WPR KEY LL_RTC_EnableWriteProtection + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableWriteProtection(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->WPR, RTC_WRITE_PROTECTION_DISABLE); +} + +/** + * @brief Disable the write protection for RTC registers. + * @rmtoll WPR KEY LL_RTC_DisableWriteProtection + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableWriteProtection(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->WPR, RTC_WRITE_PROTECTION_ENABLE_1); + WRITE_REG(RTCx->WPR, RTC_WRITE_PROTECTION_ENABLE_2); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Time Time + * @{ + */ + +/** + * @brief Set time format (AM/24-hour or PM notation) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll TR PM LL_RTC_TIME_SetFormat + * @param RTCx RTC Instance + * @param TimeFormat This parameter can be one of the following values: + * @arg @ref LL_RTC_TIME_FORMAT_AM_OR_24 + * @arg @ref LL_RTC_TIME_FORMAT_PM + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_SetFormat(RTC_TypeDef *RTCx, uint32_t TimeFormat) +{ + MODIFY_REG(RTCx->TR, RTC_TR_PM, TimeFormat); +} + +/** + * @brief Get time format (AM or PM notation) + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note Read either RTC_SSR or RTC_TR locks the values in the higher-order calendar + * shadow registers until RTC_DR is read (LL_RTC_ReadReg(RTC, DR)). + * @rmtoll TR PM LL_RTC_TIME_GetFormat + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TIME_FORMAT_AM_OR_24 + * @arg @ref LL_RTC_TIME_FORMAT_PM + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_GetFormat(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TR, RTC_TR_PM)); +} + +/** + * @brief Set Hours in BCD format + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert hour from binary to BCD format + * @rmtoll TR HT LL_RTC_TIME_SetHour\n + * TR HU LL_RTC_TIME_SetHour + * @param RTCx RTC Instance + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_SetHour(RTC_TypeDef *RTCx, uint32_t Hours) +{ + MODIFY_REG(RTCx->TR, (RTC_TR_HT | RTC_TR_HU), + (((Hours & 0xF0U) << (RTC_TR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_TR_HU_Pos))); +} + +/** + * @brief Get Hours in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note Read either RTC_SSR or RTC_TR locks the values in the higher-order calendar + * shadow registers until RTC_DR is read (LL_RTC_ReadReg(RTC, DR)). + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert hour from BCD to + * Binary format + * @rmtoll TR HT LL_RTC_TIME_GetHour\n + * TR HU LL_RTC_TIME_GetHour + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_GetHour(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->TR, (RTC_TR_HT | RTC_TR_HU))) >> RTC_TR_HU_Pos); +} + +/** + * @brief Set Minutes in BCD format + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Minutes from binary to BCD format + * @rmtoll TR MNT LL_RTC_TIME_SetMinute\n + * TR MNU LL_RTC_TIME_SetMinute + * @param RTCx RTC Instance + * @param Minutes Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_SetMinute(RTC_TypeDef *RTCx, uint32_t Minutes) +{ + MODIFY_REG(RTCx->TR, (RTC_TR_MNT | RTC_TR_MNU), + (((Minutes & 0xF0U) << (RTC_TR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_TR_MNU_Pos))); +} + +/** + * @brief Get Minutes in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note Read either RTC_SSR or RTC_TR locks the values in the higher-order calendar + * shadow registers until RTC_DR is read (LL_RTC_ReadReg(RTC, DR)). + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert minute from BCD + * to Binary format + * @rmtoll TR MNT LL_RTC_TIME_GetMinute\n + * TR MNU LL_RTC_TIME_GetMinute + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_GetMinute(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TR, (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos); +} + +/** + * @brief Set Seconds in BCD format + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Seconds from binary to BCD format + * @rmtoll TR ST LL_RTC_TIME_SetSecond\n + * TR SU LL_RTC_TIME_SetSecond + * @param RTCx RTC Instance + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_SetSecond(RTC_TypeDef *RTCx, uint32_t Seconds) +{ + MODIFY_REG(RTCx->TR, (RTC_TR_ST | RTC_TR_SU), + (((Seconds & 0xF0U) << (RTC_TR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_TR_SU_Pos))); +} + +/** + * @brief Get Seconds in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note Read either RTC_SSR or RTC_TR locks the values in the higher-order calendar + * shadow registers until RTC_DR is read (LL_RTC_ReadReg(RTC, DR)). + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Seconds from BCD + * to Binary format + * @rmtoll TR ST LL_RTC_TIME_GetSecond\n + * TR SU LL_RTC_TIME_GetSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_GetSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TR, (RTC_TR_ST | RTC_TR_SU)) >> RTC_TR_SU_Pos); +} + +/** + * @brief Set time (hour, minute and second) in BCD format + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @note TimeFormat and Hours should follow the same format + * @rmtoll TR PM LL_RTC_TIME_Config\n + * TR HT LL_RTC_TIME_Config\n + * TR HU LL_RTC_TIME_Config\n + * TR MNT LL_RTC_TIME_Config\n + * TR MNU LL_RTC_TIME_Config\n + * TR ST LL_RTC_TIME_Config\n + * TR SU LL_RTC_TIME_Config + * @param RTCx RTC Instance + * @param Format12_24 This parameter can be one of the following values: + * @arg @ref LL_RTC_TIME_FORMAT_AM_OR_24 + * @arg @ref LL_RTC_TIME_FORMAT_PM + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @param Minutes Value between Min_Data=0x00 and Max_Data=0x59 + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_Config(RTC_TypeDef *RTCx, uint32_t Format12_24, uint32_t Hours, uint32_t Minutes, uint32_t Seconds) +{ + uint32_t temp; + + temp = Format12_24 | \ + (((Hours & 0xF0U) << (RTC_TR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_TR_HU_Pos)) | \ + (((Minutes & 0xF0U) << (RTC_TR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_TR_MNU_Pos)) | \ + (((Seconds & 0xF0U) << (RTC_TR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_TR_SU_Pos)); + MODIFY_REG(RTCx->TR, (RTC_TR_PM | RTC_TR_HT | RTC_TR_HU | RTC_TR_MNT | RTC_TR_MNU | RTC_TR_ST | RTC_TR_SU), temp); +} + +/** + * @brief Get time (hour, minute and second) in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note Read either RTC_SSR or RTC_TR locks the values in the higher-order calendar + * shadow registers until RTC_DR is read (LL_RTC_ReadReg(RTC, DR)). + * @note helper macros __LL_RTC_GET_HOUR, __LL_RTC_GET_MINUTE and __LL_RTC_GET_SECOND + * are available to get independently each parameter. + * @rmtoll TR HT LL_RTC_TIME_Get\n + * TR HU LL_RTC_TIME_Get\n + * TR MNT LL_RTC_TIME_Get\n + * TR MNU LL_RTC_TIME_Get\n + * TR ST LL_RTC_TIME_Get\n + * TR SU LL_RTC_TIME_Get + * @param RTCx RTC Instance + * @retval Combination of hours, minutes and seconds (Format: 0x00HHMMSS). + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_Get(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TR, (RTC_TR_HT | RTC_TR_HU | RTC_TR_MNT | RTC_TR_MNU | RTC_TR_ST | RTC_TR_SU))); +} + +/** + * @brief Memorize whether the daylight saving time change has been performed + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR BKP LL_RTC_TIME_EnableDayLightStore + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_EnableDayLightStore(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_BKP); +} + +/** + * @brief Disable memorization whether the daylight saving time change has been performed. + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR BKP LL_RTC_TIME_DisableDayLightStore + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_DisableDayLightStore(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_BKP); +} + +/** + * @brief Check if RTC Day Light Saving stored operation has been enabled or not + * @rmtoll CR BKP LL_RTC_TIME_IsDayLightStoreEnabled + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_IsDayLightStoreEnabled(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_BKP) == (RTC_CR_BKP)) ? 1UL : 0UL); +} + +/** + * @brief Subtract 1 hour (winter time change) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR SUB1H LL_RTC_TIME_DecHour + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_DecHour(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_SUB1H); +} + +/** + * @brief Add 1 hour (summer time change) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ADD1H LL_RTC_TIME_IncHour + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_IncHour(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_ADD1H); +} + +/** + * @brief Get subseconds value in the synchronous prescaler counter. + * @note You can use both SubSeconds value and SecondFraction (PREDIV_S through + * LL_RTC_GetSynchPrescaler function) terms returned to convert Calendar + * SubSeconds value in second fraction ratio with time unit following + * generic formula: + * ==> Seconds fraction ratio * time_unit = + * [(SecondFraction-SubSeconds)/(SecondFraction+1)] * time_unit + * This conversion can be performed only if no shift operation is pending + * (ie. SHFP=0) when PREDIV_S >= SS. + * @rmtoll SSR SS LL_RTC_TIME_GetSubSecond + * @param RTCx RTC Instance + * @retval Subseconds value (number between 0 and 65535) + */ +__STATIC_INLINE uint32_t LL_RTC_TIME_GetSubSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->SSR, RTC_SSR_SS)); +} + +/** + * @brief Synchronize to a remote clock with a high degree of precision. + * @note This operation effectively subtracts from (delays) or advance the clock of a fraction of a second. + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note When REFCKON is set, firmware must not write to Shift control register. + * @rmtoll SHIFTR ADD1S LL_RTC_TIME_Synchronize\n + * SHIFTR SUBFS LL_RTC_TIME_Synchronize + * @param RTCx RTC Instance + * @param ShiftSecond This parameter can be one of the following values: + * @arg @ref LL_RTC_SHIFT_SECOND_DELAY + * @arg @ref LL_RTC_SHIFT_SECOND_ADVANCE + * @param Fraction Number of Seconds Fractions (any value from 0 to 0x7FFF) + * @retval None + */ +__STATIC_INLINE void LL_RTC_TIME_Synchronize(RTC_TypeDef *RTCx, uint32_t ShiftSecond, uint32_t Fraction) +{ + WRITE_REG(RTCx->SHIFTR, ShiftSecond | Fraction); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Date Date + * @{ + */ + +/** + * @brief Set Year in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Year from binary to BCD format + * @rmtoll DR YT LL_RTC_DATE_SetYear\n + * DR YU LL_RTC_DATE_SetYear + * @param RTCx RTC Instance + * @param Year Value between Min_Data=0x00 and Max_Data=0x99 + * @retval None + */ +__STATIC_INLINE void LL_RTC_DATE_SetYear(RTC_TypeDef *RTCx, uint32_t Year) +{ + MODIFY_REG(RTCx->DR, (RTC_DR_YT | RTC_DR_YU), + (((Year & 0xF0U) << (RTC_DR_YT_Pos - 4U)) | ((Year & 0x0FU) << RTC_DR_YU_Pos))); +} + +/** + * @brief Get Year in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Year from BCD to Binary format + * @rmtoll DR YT LL_RTC_DATE_GetYear\n + * DR YU LL_RTC_DATE_GetYear + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x99 + */ +__STATIC_INLINE uint32_t LL_RTC_DATE_GetYear(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->DR, (RTC_DR_YT | RTC_DR_YU))) >> RTC_DR_YU_Pos); +} + +/** + * @brief Set Week day + * @rmtoll DR WDU LL_RTC_DATE_SetWeekDay + * @param RTCx RTC Instance + * @param WeekDay This parameter can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + * @retval None + */ +__STATIC_INLINE void LL_RTC_DATE_SetWeekDay(RTC_TypeDef *RTCx, uint32_t WeekDay) +{ + MODIFY_REG(RTCx->DR, RTC_DR_WDU, WeekDay << RTC_DR_WDU_Pos); +} + +/** + * @brief Get Week day + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @rmtoll DR WDU LL_RTC_DATE_GetWeekDay + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + */ +__STATIC_INLINE uint32_t LL_RTC_DATE_GetWeekDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->DR, RTC_DR_WDU) >> RTC_DR_WDU_Pos); +} + +/** + * @brief Set Month in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Month from binary to BCD format + * @rmtoll DR MT LL_RTC_DATE_SetMonth\n + * DR MU LL_RTC_DATE_SetMonth + * @param RTCx RTC Instance + * @param Month This parameter can be one of the following values: + * @arg @ref LL_RTC_MONTH_JANUARY + * @arg @ref LL_RTC_MONTH_FEBRUARY + * @arg @ref LL_RTC_MONTH_MARCH + * @arg @ref LL_RTC_MONTH_APRIL + * @arg @ref LL_RTC_MONTH_MAY + * @arg @ref LL_RTC_MONTH_JUNE + * @arg @ref LL_RTC_MONTH_JULY + * @arg @ref LL_RTC_MONTH_AUGUST + * @arg @ref LL_RTC_MONTH_SEPTEMBER + * @arg @ref LL_RTC_MONTH_OCTOBER + * @arg @ref LL_RTC_MONTH_NOVEMBER + * @arg @ref LL_RTC_MONTH_DECEMBER + * @retval None + */ +__STATIC_INLINE void LL_RTC_DATE_SetMonth(RTC_TypeDef *RTCx, uint32_t Month) +{ + MODIFY_REG(RTCx->DR, (RTC_DR_MT | RTC_DR_MU), + (((Month & 0xF0U) << (RTC_DR_MT_Pos - 4U)) | ((Month & 0x0FU) << RTC_DR_MU_Pos))); +} + +/** + * @brief Get Month in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Month from BCD to Binary format + * @rmtoll DR MT LL_RTC_DATE_GetMonth\n + * DR MU LL_RTC_DATE_GetMonth + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_MONTH_JANUARY + * @arg @ref LL_RTC_MONTH_FEBRUARY + * @arg @ref LL_RTC_MONTH_MARCH + * @arg @ref LL_RTC_MONTH_APRIL + * @arg @ref LL_RTC_MONTH_MAY + * @arg @ref LL_RTC_MONTH_JUNE + * @arg @ref LL_RTC_MONTH_JULY + * @arg @ref LL_RTC_MONTH_AUGUST + * @arg @ref LL_RTC_MONTH_SEPTEMBER + * @arg @ref LL_RTC_MONTH_OCTOBER + * @arg @ref LL_RTC_MONTH_NOVEMBER + * @arg @ref LL_RTC_MONTH_DECEMBER + */ +__STATIC_INLINE uint32_t LL_RTC_DATE_GetMonth(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->DR, (RTC_DR_MT | RTC_DR_MU))) >> RTC_DR_MU_Pos); +} + +/** + * @brief Set Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Day from binary to BCD format + * @rmtoll DR DT LL_RTC_DATE_SetDay\n + * DR DU LL_RTC_DATE_SetDay + * @param RTCx RTC Instance + * @param Day Value between Min_Data=0x01 and Max_Data=0x31 + * @retval None + */ +__STATIC_INLINE void LL_RTC_DATE_SetDay(RTC_TypeDef *RTCx, uint32_t Day) +{ + MODIFY_REG(RTCx->DR, (RTC_DR_DT | RTC_DR_DU), + (((Day & 0xF0U) << (RTC_DR_DT_Pos - 4U)) | ((Day & 0x0FU) << RTC_DR_DU_Pos))); +} + +/** + * @brief Get Day in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Day from BCD to Binary format + * @rmtoll DR DT LL_RTC_DATE_GetDay\n + * DR DU LL_RTC_DATE_GetDay + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x31 + */ +__STATIC_INLINE uint32_t LL_RTC_DATE_GetDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->DR, (RTC_DR_DT | RTC_DR_DU))) >> RTC_DR_DU_Pos); +} + +/** + * @brief Set date (WeekDay, Day, Month and Year) in BCD format + * @rmtoll DR WDU LL_RTC_DATE_Config\n + * DR MT LL_RTC_DATE_Config\n + * DR MU LL_RTC_DATE_Config\n + * DR DT LL_RTC_DATE_Config\n + * DR DU LL_RTC_DATE_Config\n + * DR YT LL_RTC_DATE_Config\n + * DR YU LL_RTC_DATE_Config + * @param RTCx RTC Instance + * @param WeekDay This parameter can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + * @param Day Value between Min_Data=0x01 and Max_Data=0x31 + * @param Month This parameter can be one of the following values: + * @arg @ref LL_RTC_MONTH_JANUARY + * @arg @ref LL_RTC_MONTH_FEBRUARY + * @arg @ref LL_RTC_MONTH_MARCH + * @arg @ref LL_RTC_MONTH_APRIL + * @arg @ref LL_RTC_MONTH_MAY + * @arg @ref LL_RTC_MONTH_JUNE + * @arg @ref LL_RTC_MONTH_JULY + * @arg @ref LL_RTC_MONTH_AUGUST + * @arg @ref LL_RTC_MONTH_SEPTEMBER + * @arg @ref LL_RTC_MONTH_OCTOBER + * @arg @ref LL_RTC_MONTH_NOVEMBER + * @arg @ref LL_RTC_MONTH_DECEMBER + * @param Year Value between Min_Data=0x00 and Max_Data=0x99 + * @retval None + */ +__STATIC_INLINE void LL_RTC_DATE_Config(RTC_TypeDef *RTCx, uint32_t WeekDay, uint32_t Day, uint32_t Month, uint32_t Year) +{ + uint32_t temp; + + temp = ( WeekDay << RTC_DR_WDU_Pos) | \ + (((Year & 0xF0U) << (RTC_DR_YT_Pos - 4U)) | ((Year & 0x0FU) << RTC_DR_YU_Pos)) | \ + (((Month & 0xF0U) << (RTC_DR_MT_Pos - 4U)) | ((Month & 0x0FU) << RTC_DR_MU_Pos)) | \ + (((Day & 0xF0U) << (RTC_DR_DT_Pos - 4U)) | ((Day & 0x0FU) << RTC_DR_DU_Pos)); + + MODIFY_REG(RTCx->DR, (RTC_DR_WDU | RTC_DR_MT | RTC_DR_MU | RTC_DR_DT | RTC_DR_DU | RTC_DR_YT | RTC_DR_YU), temp); +} + +/** + * @brief Get date (WeekDay, Day, Month and Year) in BCD format + * @note if RTC shadow registers are not bypassed (BYPSHAD=0), need to check if RSF flag is set + * before reading this bit + * @note helper macros __LL_RTC_GET_WEEKDAY, __LL_RTC_GET_YEAR, __LL_RTC_GET_MONTH, + * and __LL_RTC_GET_DAY are available to get independently each parameter. + * @rmtoll DR WDU LL_RTC_DATE_Get\n + * DR MT LL_RTC_DATE_Get\n + * DR MU LL_RTC_DATE_Get\n + * DR DT LL_RTC_DATE_Get\n + * DR DU LL_RTC_DATE_Get\n + * DR YT LL_RTC_DATE_Get\n + * DR YU LL_RTC_DATE_Get + * @param RTCx RTC Instance + * @retval Combination of WeekDay, Day, Month and Year (Format: 0xWWDDMMYY). + */ +__STATIC_INLINE uint32_t LL_RTC_DATE_Get(RTC_TypeDef *RTCx) +{ + uint32_t temp; + + temp = READ_BIT(RTCx->DR, (RTC_DR_WDU | RTC_DR_MT | RTC_DR_MU | RTC_DR_DT | RTC_DR_DU | RTC_DR_YT | RTC_DR_YU)); + + return (uint32_t)((((temp & RTC_DR_WDU) >> RTC_DR_WDU_Pos) << RTC_OFFSET_WEEKDAY) | \ + (((temp & (RTC_DR_DT | RTC_DR_DU)) >> RTC_DR_DU_Pos) << RTC_OFFSET_DAY) | \ + (((temp & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos) << RTC_OFFSET_MONTH) | \ + ((temp & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_ALARMA ALARMA + * @{ + */ + +/** + * @brief Enable Alarm A + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRAE LL_RTC_ALMA_Enable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_Enable(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_ALRAE); +} + +/** + * @brief Disable Alarm A + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRAE LL_RTC_ALMA_Disable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_Disable(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_ALRAE); +} + +/** + * @brief Specify the Alarm A masks. + * @rmtoll ALRMAR MSK4 LL_RTC_ALMA_SetMask\n + * ALRMAR MSK3 LL_RTC_ALMA_SetMask\n + * ALRMAR MSK2 LL_RTC_ALMA_SetMask\n + * ALRMAR MSK1 LL_RTC_ALMA_SetMask + * @param RTCx RTC Instance + * @param Mask This parameter can be a combination of the following values: + * @arg @ref LL_RTC_ALMA_MASK_NONE + * @arg @ref LL_RTC_ALMA_MASK_DATEWEEKDAY + * @arg @ref LL_RTC_ALMA_MASK_HOURS + * @arg @ref LL_RTC_ALMA_MASK_MINUTES + * @arg @ref LL_RTC_ALMA_MASK_SECONDS + * @arg @ref LL_RTC_ALMA_MASK_ALL + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetMask(RTC_TypeDef *RTCx, uint32_t Mask) +{ + MODIFY_REG(RTCx->ALRMAR, RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1, Mask); +} + +/** + * @brief Get the Alarm A masks. + * @rmtoll ALRMAR MSK4 LL_RTC_ALMA_GetMask\n + * ALRMAR MSK3 LL_RTC_ALMA_GetMask\n + * ALRMAR MSK2 LL_RTC_ALMA_GetMask\n + * ALRMAR MSK1 LL_RTC_ALMA_GetMask + * @param RTCx RTC Instance + * @retval Returned value can be can be a combination of the following values: + * @arg @ref LL_RTC_ALMA_MASK_NONE + * @arg @ref LL_RTC_ALMA_MASK_DATEWEEKDAY + * @arg @ref LL_RTC_ALMA_MASK_HOURS + * @arg @ref LL_RTC_ALMA_MASK_MINUTES + * @arg @ref LL_RTC_ALMA_MASK_SECONDS + * @arg @ref LL_RTC_ALMA_MASK_ALL + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetMask(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMAR, RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1)); +} + +/** + * @brief Enable AlarmA Week day selection (DU[3:0] represents the week day. DT[1:0] is do not care) + * @rmtoll ALRMAR WDSEL LL_RTC_ALMA_EnableWeekday + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_EnableWeekday(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->ALRMAR, RTC_ALRMAR_WDSEL); +} + +/** + * @brief Disable AlarmA Week day selection (DU[3:0] represents the date ) + * @rmtoll ALRMAR WDSEL LL_RTC_ALMA_DisableWeekday + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_DisableWeekday(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->ALRMAR, RTC_ALRMAR_WDSEL); +} + +/** + * @brief Set ALARM A Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Day from binary to BCD format + * @rmtoll ALRMAR DT LL_RTC_ALMA_SetDay\n + * ALRMAR DU LL_RTC_ALMA_SetDay + * @param RTCx RTC Instance + * @param Day Value between Min_Data=0x01 and Max_Data=0x31 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetDay(RTC_TypeDef *RTCx, uint32_t Day) +{ + MODIFY_REG(RTCx->ALRMAR, (RTC_ALRMAR_DT | RTC_ALRMAR_DU), + (((Day & 0xF0U) << (RTC_ALRMAR_DT_Pos - 4U)) | ((Day & 0x0FU) << RTC_ALRMAR_DU_Pos))); +} + +/** + * @brief Get ALARM A Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Day from BCD to Binary format + * @rmtoll ALRMAR DT LL_RTC_ALMA_GetDay\n + * ALRMAR DU LL_RTC_ALMA_GetDay + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x31 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMAR, (RTC_ALRMAR_DT | RTC_ALRMAR_DU))) >> RTC_ALRMAR_DU_Pos); +} + +/** + * @brief Set ALARM A Weekday + * @rmtoll ALRMAR DU LL_RTC_ALMA_SetWeekDay + * @param RTCx RTC Instance + * @param WeekDay This parameter can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetWeekDay(RTC_TypeDef *RTCx, uint32_t WeekDay) +{ + MODIFY_REG(RTCx->ALRMAR, RTC_ALRMAR_DU, WeekDay << RTC_ALRMAR_DU_Pos); +} + +/** + * @brief Get ALARM A Weekday + * @rmtoll ALRMAR DU LL_RTC_ALMA_GetWeekDay + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetWeekDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMAR, RTC_ALRMAR_DU) >> RTC_ALRMAR_DU_Pos); +} + +/** + * @brief Set Alarm A time format (AM/24-hour or PM notation) + * @rmtoll ALRMAR PM LL_RTC_ALMA_SetTimeFormat + * @param RTCx RTC Instance + * @param TimeFormat This parameter can be one of the following values: + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_PM + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetTimeFormat(RTC_TypeDef *RTCx, uint32_t TimeFormat) +{ + MODIFY_REG(RTCx->ALRMAR, RTC_ALRMAR_PM, TimeFormat); +} + +/** + * @brief Get Alarm A time format (AM or PM notation) + * @rmtoll ALRMAR PM LL_RTC_ALMA_GetTimeFormat + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_PM + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetTimeFormat(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMAR, RTC_ALRMAR_PM)); +} + +/** + * @brief Set ALARM A Hours in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Hours from binary to BCD format + * @rmtoll ALRMAR HT LL_RTC_ALMA_SetHour\n + * ALRMAR HU LL_RTC_ALMA_SetHour + * @param RTCx RTC Instance + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetHour(RTC_TypeDef *RTCx, uint32_t Hours) +{ + MODIFY_REG(RTCx->ALRMAR, (RTC_ALRMAR_HT | RTC_ALRMAR_HU), + (((Hours & 0xF0U) << (RTC_ALRMAR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_ALRMAR_HU_Pos))); +} + +/** + * @brief Get ALARM A Hours in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Hours from BCD to Binary format + * @rmtoll ALRMAR HT LL_RTC_ALMA_GetHour\n + * ALRMAR HU LL_RTC_ALMA_GetHour + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetHour(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMAR, (RTC_ALRMAR_HT | RTC_ALRMAR_HU))) >> RTC_ALRMAR_HU_Pos); +} + +/** + * @brief Set ALARM A Minutes in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Minutes from binary to BCD format + * @rmtoll ALRMAR MNT LL_RTC_ALMA_SetMinute\n + * ALRMAR MNU LL_RTC_ALMA_SetMinute + * @param RTCx RTC Instance + * @param Minutes Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetMinute(RTC_TypeDef *RTCx, uint32_t Minutes) +{ + MODIFY_REG(RTCx->ALRMAR, (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU), + (((Minutes & 0xF0U) << (RTC_ALRMAR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_ALRMAR_MNU_Pos))); +} + +/** + * @brief Get ALARM A Minutes in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Minutes from BCD to Binary format + * @rmtoll ALRMAR MNT LL_RTC_ALMA_GetMinute\n + * ALRMAR MNU LL_RTC_ALMA_GetMinute + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetMinute(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMAR, (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU))) >> RTC_ALRMAR_MNU_Pos); +} + +/** + * @brief Set ALARM A Seconds in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Seconds from binary to BCD format + * @rmtoll ALRMAR ST LL_RTC_ALMA_SetSecond\n + * ALRMAR SU LL_RTC_ALMA_SetSecond + * @param RTCx RTC Instance + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetSecond(RTC_TypeDef *RTCx, uint32_t Seconds) +{ + MODIFY_REG(RTCx->ALRMAR, (RTC_ALRMAR_ST | RTC_ALRMAR_SU), + (((Seconds & 0xF0U) << (RTC_ALRMAR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_ALRMAR_SU_Pos))); +} + +/** + * @brief Get ALARM A Seconds in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Seconds from BCD to Binary format + * @rmtoll ALRMAR ST LL_RTC_ALMA_GetSecond\n + * ALRMAR SU LL_RTC_ALMA_GetSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMAR, (RTC_ALRMAR_ST | RTC_ALRMAR_SU))) >> RTC_ALRMAR_SU_Pos); +} + +/** + * @brief Set Alarm A Time (hour, minute and second) in BCD format + * @rmtoll ALRMAR PM LL_RTC_ALMA_ConfigTime\n + * ALRMAR HT LL_RTC_ALMA_ConfigTime\n + * ALRMAR HU LL_RTC_ALMA_ConfigTime\n + * ALRMAR MNT LL_RTC_ALMA_ConfigTime\n + * ALRMAR MNU LL_RTC_ALMA_ConfigTime\n + * ALRMAR ST LL_RTC_ALMA_ConfigTime\n + * ALRMAR SU LL_RTC_ALMA_ConfigTime + * @param RTCx RTC Instance + * @param Format12_24 This parameter can be one of the following values: + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMA_TIME_FORMAT_PM + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @param Minutes Value between Min_Data=0x00 and Max_Data=0x59 + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_ConfigTime(RTC_TypeDef *RTCx, uint32_t Format12_24, uint32_t Hours, uint32_t Minutes, uint32_t Seconds) +{ + uint32_t temp; + + temp = Format12_24 | \ + (((Hours & 0xF0U) << (RTC_ALRMAR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_ALRMAR_HU_Pos)) | \ + (((Minutes & 0xF0U) << (RTC_ALRMAR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_ALRMAR_MNU_Pos)) | \ + (((Seconds & 0xF0U) << (RTC_ALRMAR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_ALRMAR_SU_Pos)); + + MODIFY_REG(RTCx->ALRMAR, RTC_ALRMAR_PM | RTC_ALRMAR_HT | RTC_ALRMAR_HU | RTC_ALRMAR_MNT | RTC_ALRMAR_MNU | RTC_ALRMAR_ST | RTC_ALRMAR_SU, temp); +} + +/** + * @brief Get Alarm B Time (hour, minute and second) in BCD format + * @note helper macros __LL_RTC_GET_HOUR, __LL_RTC_GET_MINUTE and __LL_RTC_GET_SECOND + * are available to get independently each parameter. + * @rmtoll ALRMAR HT LL_RTC_ALMA_GetTime\n + * ALRMAR HU LL_RTC_ALMA_GetTime\n + * ALRMAR MNT LL_RTC_ALMA_GetTime\n + * ALRMAR MNU LL_RTC_ALMA_GetTime\n + * ALRMAR ST LL_RTC_ALMA_GetTime\n + * ALRMAR SU LL_RTC_ALMA_GetTime + * @param RTCx RTC Instance + * @retval Combination of hours, minutes and seconds. + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetTime(RTC_TypeDef *RTCx) +{ + return (uint32_t)((LL_RTC_ALMA_GetHour(RTCx) << RTC_OFFSET_HOUR) | (LL_RTC_ALMA_GetMinute(RTCx) << RTC_OFFSET_MINUTE) | LL_RTC_ALMA_GetSecond(RTCx)); +} + +/** + * @brief Mask the most-significant bits of the subseconds field starting from + * the bit specified in parameter Mask + * @note This register can be written only when ALRAE is reset in RTC_CR register, + * or in initialization mode. + * @rmtoll ALRMASSR MASKSS LL_RTC_ALMA_SetSubSecondMask + * @param RTCx RTC Instance + * @param Mask Value between Min_Data=0x00 and Max_Data=0xF + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetSubSecondMask(RTC_TypeDef *RTCx, uint32_t Mask) +{ + MODIFY_REG(RTCx->ALRMASSR, RTC_ALRMASSR_MASKSS, Mask << RTC_ALRMASSR_MASKSS_Pos); +} + +/** + * @brief Get Alarm A subseconds mask + * @rmtoll ALRMASSR MASKSS LL_RTC_ALMA_GetSubSecondMask + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetSubSecondMask(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMASSR, RTC_ALRMASSR_MASKSS) >> RTC_ALRMASSR_MASKSS_Pos); +} + +/** + * @brief Set Alarm A subseconds value + * @rmtoll ALRMASSR SS LL_RTC_ALMA_SetSubSecond + * @param RTCx RTC Instance + * @param Subsecond Value between Min_Data=0x00 and Max_Data=0x7FFF + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMA_SetSubSecond(RTC_TypeDef *RTCx, uint32_t Subsecond) +{ + MODIFY_REG(RTCx->ALRMASSR, RTC_ALRMASSR_SS, Subsecond); +} + +/** + * @brief Get Alarm A subseconds value + * @rmtoll ALRMASSR SS LL_RTC_ALMA_GetSubSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x7FFF + */ +__STATIC_INLINE uint32_t LL_RTC_ALMA_GetSubSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMASSR, RTC_ALRMASSR_SS)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_ALARMB ALARMB + * @{ + */ + +/** + * @brief Enable Alarm B + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRBE LL_RTC_ALMB_Enable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_Enable(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_ALRBE); +} + +/** + * @brief Disable Alarm B + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRBE LL_RTC_ALMB_Disable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_Disable(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_ALRBE); +} + +/** + * @brief Specify the Alarm B masks. + * @rmtoll ALRMBR MSK4 LL_RTC_ALMB_SetMask\n + * ALRMBR MSK3 LL_RTC_ALMB_SetMask\n + * ALRMBR MSK2 LL_RTC_ALMB_SetMask\n + * ALRMBR MSK1 LL_RTC_ALMB_SetMask + * @param RTCx RTC Instance + * @param Mask This parameter can be a combination of the following values: + * @arg @ref LL_RTC_ALMB_MASK_NONE + * @arg @ref LL_RTC_ALMB_MASK_DATEWEEKDAY + * @arg @ref LL_RTC_ALMB_MASK_HOURS + * @arg @ref LL_RTC_ALMB_MASK_MINUTES + * @arg @ref LL_RTC_ALMB_MASK_SECONDS + * @arg @ref LL_RTC_ALMB_MASK_ALL + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetMask(RTC_TypeDef *RTCx, uint32_t Mask) +{ + MODIFY_REG(RTCx->ALRMBR, RTC_ALRMBR_MSK4 | RTC_ALRMBR_MSK3 | RTC_ALRMBR_MSK2 | RTC_ALRMBR_MSK1, Mask); +} + +/** + * @brief Get the Alarm B masks. + * @rmtoll ALRMBR MSK4 LL_RTC_ALMB_GetMask\n + * ALRMBR MSK3 LL_RTC_ALMB_GetMask\n + * ALRMBR MSK2 LL_RTC_ALMB_GetMask\n + * ALRMBR MSK1 LL_RTC_ALMB_GetMask + * @param RTCx RTC Instance + * @retval Returned value can be can be a combination of the following values: + * @arg @ref LL_RTC_ALMB_MASK_NONE + * @arg @ref LL_RTC_ALMB_MASK_DATEWEEKDAY + * @arg @ref LL_RTC_ALMB_MASK_HOURS + * @arg @ref LL_RTC_ALMB_MASK_MINUTES + * @arg @ref LL_RTC_ALMB_MASK_SECONDS + * @arg @ref LL_RTC_ALMB_MASK_ALL + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetMask(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMBR, RTC_ALRMBR_MSK4 | RTC_ALRMBR_MSK3 | RTC_ALRMBR_MSK2 | RTC_ALRMBR_MSK1)); +} + +/** + * @brief Enable AlarmB Week day selection (DU[3:0] represents the week day. DT[1:0] is do not care) + * @rmtoll ALRMBR WDSEL LL_RTC_ALMB_EnableWeekday + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_EnableWeekday(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->ALRMBR, RTC_ALRMBR_WDSEL); +} + +/** + * @brief Disable AlarmB Week day selection (DU[3:0] represents the date ) + * @rmtoll ALRMBR WDSEL LL_RTC_ALMB_DisableWeekday + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_DisableWeekday(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->ALRMBR, RTC_ALRMBR_WDSEL); +} + +/** + * @brief Set ALARM B Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Day from binary to BCD format + * @rmtoll ALRMBR DT LL_RTC_ALMB_SetDay\n + * ALRMBR DU LL_RTC_ALMB_SetDay + * @param RTCx RTC Instance + * @param Day Value between Min_Data=0x01 and Max_Data=0x31 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetDay(RTC_TypeDef *RTCx, uint32_t Day) +{ + MODIFY_REG(RTCx->ALRMBR, (RTC_ALRMBR_DT | RTC_ALRMBR_DU), + (((Day & 0xF0U) << (RTC_ALRMBR_DT_Pos - 4U)) | ((Day & 0x0FU) << RTC_ALRMBR_DU_Pos))); +} + +/** + * @brief Get ALARM B Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Day from BCD to Binary format + * @rmtoll ALRMBR DT LL_RTC_ALMB_GetDay\n + * ALRMBR DU LL_RTC_ALMB_GetDay + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x31 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMBR, (RTC_ALRMBR_DT | RTC_ALRMBR_DU))) >> RTC_ALRMBR_DU_Pos); +} + +/** + * @brief Set ALARM B Weekday + * @rmtoll ALRMBR DU LL_RTC_ALMB_SetWeekDay + * @param RTCx RTC Instance + * @param WeekDay This parameter can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetWeekDay(RTC_TypeDef *RTCx, uint32_t WeekDay) +{ + MODIFY_REG(RTCx->ALRMBR, RTC_ALRMBR_DU, WeekDay << RTC_ALRMBR_DU_Pos); +} + +/** + * @brief Get ALARM B Weekday + * @rmtoll ALRMBR DU LL_RTC_ALMB_GetWeekDay + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetWeekDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMBR, RTC_ALRMBR_DU) >> RTC_ALRMBR_DU_Pos); +} + +/** + * @brief Set ALARM B time format (AM/24-hour or PM notation) + * @rmtoll ALRMBR PM LL_RTC_ALMB_SetTimeFormat + * @param RTCx RTC Instance + * @param TimeFormat This parameter can be one of the following values: + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_PM + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetTimeFormat(RTC_TypeDef *RTCx, uint32_t TimeFormat) +{ + MODIFY_REG(RTCx->ALRMBR, RTC_ALRMBR_PM, TimeFormat); +} + +/** + * @brief Get ALARM B time format (AM or PM notation) + * @rmtoll ALRMBR PM LL_RTC_ALMB_GetTimeFormat + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_PM + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetTimeFormat(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMBR, RTC_ALRMBR_PM)); +} + +/** + * @brief Set ALARM B Hours in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Hours from binary to BCD format + * @rmtoll ALRMBR HT LL_RTC_ALMB_SetHour\n + * ALRMBR HU LL_RTC_ALMB_SetHour + * @param RTCx RTC Instance + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetHour(RTC_TypeDef *RTCx, uint32_t Hours) +{ + MODIFY_REG(RTCx->ALRMBR, (RTC_ALRMBR_HT | RTC_ALRMBR_HU), + (((Hours & 0xF0U) << (RTC_ALRMBR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_ALRMBR_HU_Pos))); +} + +/** + * @brief Get ALARM B Hours in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Hours from BCD to Binary format + * @rmtoll ALRMBR HT LL_RTC_ALMB_GetHour\n + * ALRMBR HU LL_RTC_ALMB_GetHour + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetHour(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMBR, (RTC_ALRMBR_HT | RTC_ALRMBR_HU))) >> RTC_ALRMBR_HU_Pos); +} + +/** + * @brief Set ALARM B Minutes in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Minutes from binary to BCD format + * @rmtoll ALRMBR MNT LL_RTC_ALMB_SetMinute\n + * ALRMBR MNU LL_RTC_ALMB_SetMinute + * @param RTCx RTC Instance + * @param Minutes between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetMinute(RTC_TypeDef *RTCx, uint32_t Minutes) +{ + MODIFY_REG(RTCx->ALRMBR, (RTC_ALRMBR_MNT | RTC_ALRMBR_MNU), + (((Minutes & 0xF0U) << (RTC_ALRMBR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_ALRMBR_MNU_Pos))); +} + +/** + * @brief Get ALARM B Minutes in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Minutes from BCD to Binary format + * @rmtoll ALRMBR MNT LL_RTC_ALMB_GetMinute\n + * ALRMBR MNU LL_RTC_ALMB_GetMinute + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetMinute(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMBR, (RTC_ALRMBR_MNT | RTC_ALRMBR_MNU))) >> RTC_ALRMBR_MNU_Pos); +} + +/** + * @brief Set ALARM B Seconds in BCD format + * @note helper macro __LL_RTC_CONVERT_BIN2BCD is available to convert Seconds from binary to BCD format + * @rmtoll ALRMBR ST LL_RTC_ALMB_SetSecond\n + * ALRMBR SU LL_RTC_ALMB_SetSecond + * @param RTCx RTC Instance + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetSecond(RTC_TypeDef *RTCx, uint32_t Seconds) +{ + MODIFY_REG(RTCx->ALRMBR, (RTC_ALRMBR_ST | RTC_ALRMBR_SU), + (((Seconds & 0xF0U) << (RTC_ALRMBR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_ALRMBR_SU_Pos))); +} + +/** + * @brief Get ALARM B Seconds in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Seconds from BCD to Binary format + * @rmtoll ALRMBR ST LL_RTC_ALMB_GetSecond\n + * ALRMBR SU LL_RTC_ALMB_GetSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)((READ_BIT(RTCx->ALRMBR, (RTC_ALRMBR_ST | RTC_ALRMBR_SU))) >> RTC_ALRMBR_SU_Pos); +} + +/** + * @brief Set Alarm B Time (hour, minute and second) in BCD format + * @rmtoll ALRMBR PM LL_RTC_ALMB_ConfigTime\n + * ALRMBR HT LL_RTC_ALMB_ConfigTime\n + * ALRMBR HU LL_RTC_ALMB_ConfigTime\n + * ALRMBR MNT LL_RTC_ALMB_ConfigTime\n + * ALRMBR MNU LL_RTC_ALMB_ConfigTime\n + * ALRMBR ST LL_RTC_ALMB_ConfigTime\n + * ALRMBR SU LL_RTC_ALMB_ConfigTime + * @param RTCx RTC Instance + * @param Format12_24 This parameter can be one of the following values: + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_AM + * @arg @ref LL_RTC_ALMB_TIME_FORMAT_PM + * @param Hours Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + * @param Minutes Value between Min_Data=0x00 and Max_Data=0x59 + * @param Seconds Value between Min_Data=0x00 and Max_Data=0x59 + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_ConfigTime(RTC_TypeDef *RTCx, uint32_t Format12_24, uint32_t Hours, uint32_t Minutes, uint32_t Seconds) +{ + uint32_t temp; + + temp = Format12_24 | \ + (((Hours & 0xF0U) << (RTC_ALRMBR_HT_Pos - 4U)) | ((Hours & 0x0FU) << RTC_ALRMBR_HU_Pos)) | \ + (((Minutes & 0xF0U) << (RTC_ALRMBR_MNT_Pos - 4U)) | ((Minutes & 0x0FU) << RTC_ALRMBR_MNU_Pos)) | \ + (((Seconds & 0xF0U) << (RTC_ALRMBR_ST_Pos - 4U)) | ((Seconds & 0x0FU) << RTC_ALRMBR_SU_Pos)); + + MODIFY_REG(RTCx->ALRMBR, RTC_ALRMBR_PM | RTC_ALRMBR_HT | RTC_ALRMBR_HU | RTC_ALRMBR_MNT | RTC_ALRMBR_MNU | RTC_ALRMBR_ST | RTC_ALRMBR_SU, temp); +} + +/** + * @brief Get Alarm B Time (hour, minute and second) in BCD format + * @note helper macros __LL_RTC_GET_HOUR, __LL_RTC_GET_MINUTE and __LL_RTC_GET_SECOND + * are available to get independently each parameter. + * @rmtoll ALRMBR HT LL_RTC_ALMB_GetTime\n + * ALRMBR HU LL_RTC_ALMB_GetTime\n + * ALRMBR MNT LL_RTC_ALMB_GetTime\n + * ALRMBR MNU LL_RTC_ALMB_GetTime\n + * ALRMBR ST LL_RTC_ALMB_GetTime\n + * ALRMBR SU LL_RTC_ALMB_GetTime + * @param RTCx RTC Instance + * @retval Combination of hours, minutes and seconds. + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetTime(RTC_TypeDef *RTCx) +{ + return (uint32_t)((LL_RTC_ALMB_GetHour(RTCx) << RTC_OFFSET_HOUR) | (LL_RTC_ALMB_GetMinute(RTCx) << RTC_OFFSET_MINUTE) | LL_RTC_ALMB_GetSecond(RTCx)); +} + +/** + * @brief Mask the most-significant bits of the subseconds field starting from + * the bit specified in parameter Mask + * @note This register can be written only when ALRBE is reset in RTC_CR register, + * or in initialization mode. + * @rmtoll ALRMBSSR MASKSS LL_RTC_ALMB_SetSubSecondMask + * @param RTCx RTC Instance + * @param Mask Value between Min_Data=0x00 and Max_Data=0xF + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetSubSecondMask(RTC_TypeDef *RTCx, uint32_t Mask) +{ + MODIFY_REG(RTCx->ALRMBSSR, RTC_ALRMBSSR_MASKSS, Mask << RTC_ALRMBSSR_MASKSS_Pos); +} + +/** + * @brief Get Alarm B subseconds mask + * @rmtoll ALRMBSSR MASKSS LL_RTC_ALMB_GetSubSecondMask + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xF + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetSubSecondMask(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMBSSR, RTC_ALRMBSSR_MASKSS) >> RTC_ALRMBSSR_MASKSS_Pos); +} + +/** + * @brief Set Alarm B subseconds value + * @rmtoll ALRMBSSR SS LL_RTC_ALMB_SetSubSecond + * @param RTCx RTC Instance + * @param Subsecond Value between Min_Data=0x00 and Max_Data=0x7FFF + * @retval None + */ +__STATIC_INLINE void LL_RTC_ALMB_SetSubSecond(RTC_TypeDef *RTCx, uint32_t Subsecond) +{ + MODIFY_REG(RTCx->ALRMBSSR, RTC_ALRMBSSR_SS, Subsecond); +} + +/** + * @brief Get Alarm B subseconds value + * @rmtoll ALRMBSSR SS LL_RTC_ALMB_GetSubSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x7FFF + */ +__STATIC_INLINE uint32_t LL_RTC_ALMB_GetSubSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->ALRMBSSR, RTC_ALRMBSSR_SS)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Timestamp Timestamp + * @{ + */ + +/** + * @brief Enable Timestamp + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR TSE LL_RTC_TS_Enable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_Enable(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_TSE); +} + +/** + * @brief Disable Timestamp + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR TSE LL_RTC_TS_Disable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_Disable(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_TSE); +} + +/** + * @brief Set Time-stamp event active edge + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note TSE must be reset when TSEDGE is changed to avoid unwanted TSF setting + * @rmtoll CR TSEDGE LL_RTC_TS_SetActiveEdge + * @param RTCx RTC Instance + * @param Edge This parameter can be one of the following values: + * @arg @ref LL_RTC_TIMESTAMP_EDGE_RISING + * @arg @ref LL_RTC_TIMESTAMP_EDGE_FALLING + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_SetActiveEdge(RTC_TypeDef *RTCx, uint32_t Edge) +{ + MODIFY_REG(RTCx->CR, RTC_CR_TSEDGE, Edge); +} + +/** + * @brief Get Time-stamp event active edge + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR TSEDGE LL_RTC_TS_GetActiveEdge + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TIMESTAMP_EDGE_RISING + * @arg @ref LL_RTC_TIMESTAMP_EDGE_FALLING + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetActiveEdge(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_TSEDGE)); +} + +/** + * @brief Get Timestamp AM/PM notation (AM or 24-hour format) + * @rmtoll TSTR PM LL_RTC_TS_GetTimeFormat + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TS_TIME_FORMAT_AM + * @arg @ref LL_RTC_TS_TIME_FORMAT_PM + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetTimeFormat(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSTR, RTC_TSTR_PM)); +} + +/** + * @brief Get Timestamp Hours in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Hours from BCD to Binary format + * @rmtoll TSTR HT LL_RTC_TS_GetHour\n + * TSTR HU LL_RTC_TS_GetHour + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x12 or between Min_Data=0x00 and Max_Data=0x23 + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetHour(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSTR, RTC_TSTR_HT | RTC_TSTR_HU) >> RTC_TSTR_HU_Pos); +} + +/** + * @brief Get Timestamp Minutes in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Minutes from BCD to Binary format + * @rmtoll TSTR MNT LL_RTC_TS_GetMinute\n + * TSTR MNU LL_RTC_TS_GetMinute + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetMinute(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSTR, RTC_TSTR_MNT | RTC_TSTR_MNU) >> RTC_TSTR_MNU_Pos); +} + +/** + * @brief Get Timestamp Seconds in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Seconds from BCD to Binary format + * @rmtoll TSTR ST LL_RTC_TS_GetSecond\n + * TSTR SU LL_RTC_TS_GetSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0x59 + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSTR, RTC_TSTR_ST | RTC_TSTR_SU)); +} + +/** + * @brief Get Timestamp time (hour, minute and second) in BCD format + * @note helper macros __LL_RTC_GET_HOUR, __LL_RTC_GET_MINUTE and __LL_RTC_GET_SECOND + * are available to get independently each parameter. + * @rmtoll TSTR HT LL_RTC_TS_GetTime\n + * TSTR HU LL_RTC_TS_GetTime\n + * TSTR MNT LL_RTC_TS_GetTime\n + * TSTR MNU LL_RTC_TS_GetTime\n + * TSTR ST LL_RTC_TS_GetTime\n + * TSTR SU LL_RTC_TS_GetTime + * @param RTCx RTC Instance + * @retval Combination of hours, minutes and seconds. + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetTime(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSTR, + RTC_TSTR_HT | RTC_TSTR_HU | RTC_TSTR_MNT | RTC_TSTR_MNU | RTC_TSTR_ST | RTC_TSTR_SU)); +} + +/** + * @brief Get Timestamp Week day + * @rmtoll TSDR WDU LL_RTC_TS_GetWeekDay + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WEEKDAY_MONDAY + * @arg @ref LL_RTC_WEEKDAY_TUESDAY + * @arg @ref LL_RTC_WEEKDAY_WEDNESDAY + * @arg @ref LL_RTC_WEEKDAY_THURSDAY + * @arg @ref LL_RTC_WEEKDAY_FRIDAY + * @arg @ref LL_RTC_WEEKDAY_SATURDAY + * @arg @ref LL_RTC_WEEKDAY_SUNDAY + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetWeekDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSDR, RTC_TSDR_WDU) >> RTC_TSDR_WDU_Pos); +} + +/** + * @brief Get Timestamp Month in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Month from BCD to Binary format + * @rmtoll TSDR MT LL_RTC_TS_GetMonth\n + * TSDR MU LL_RTC_TS_GetMonth + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_MONTH_JANUARY + * @arg @ref LL_RTC_MONTH_FEBRUARY + * @arg @ref LL_RTC_MONTH_MARCH + * @arg @ref LL_RTC_MONTH_APRIL + * @arg @ref LL_RTC_MONTH_MAY + * @arg @ref LL_RTC_MONTH_JUNE + * @arg @ref LL_RTC_MONTH_JULY + * @arg @ref LL_RTC_MONTH_AUGUST + * @arg @ref LL_RTC_MONTH_SEPTEMBER + * @arg @ref LL_RTC_MONTH_OCTOBER + * @arg @ref LL_RTC_MONTH_NOVEMBER + * @arg @ref LL_RTC_MONTH_DECEMBER + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetMonth(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSDR, RTC_TSDR_MT | RTC_TSDR_MU) >> RTC_TSDR_MU_Pos); +} + +/** + * @brief Get Timestamp Day in BCD format + * @note helper macro __LL_RTC_CONVERT_BCD2BIN is available to convert Day from BCD to Binary format + * @rmtoll TSDR DT LL_RTC_TS_GetDay\n + * TSDR DU LL_RTC_TS_GetDay + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x01 and Max_Data=0x31 + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetDay(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSDR, RTC_TSDR_DT | RTC_TSDR_DU)); +} + +/** + * @brief Get Timestamp date (WeekDay, Day and Month) in BCD format + * @note helper macros __LL_RTC_GET_WEEKDAY, __LL_RTC_GET_MONTH, + * and __LL_RTC_GET_DAY are available to get independently each parameter. + * @rmtoll TSDR WDU LL_RTC_TS_GetDate\n + * TSDR MT LL_RTC_TS_GetDate\n + * TSDR MU LL_RTC_TS_GetDate\n + * TSDR DT LL_RTC_TS_GetDate\n + * TSDR DU LL_RTC_TS_GetDate + * @param RTCx RTC Instance + * @retval Combination of Weekday, Day and Month + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetDate(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSDR, RTC_TSDR_WDU | RTC_TSDR_MT | RTC_TSDR_MU | RTC_TSDR_DT | RTC_TSDR_DU)); +} + +/** + * @brief Get time-stamp subseconds value + * @rmtoll TSSSR SS LL_RTC_TS_GetSubSecond + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetSubSecond(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TSSSR, RTC_TSSSR_SS)); +} + +#if defined(RTC_TAFCR_TAMPTS) +/** + * @brief Activate timestamp on tamper detection event + * @rmtoll TAFCR TAMPTS LL_RTC_TS_EnableOnTamper + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_EnableOnTamper(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPTS); +} + +/** + * @brief Disable timestamp on tamper detection event + * @rmtoll TAFCR TAMPTS LL_RTC_TS_DisableOnTamper + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_DisableOnTamper(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPTS); +} +#endif /* RTC_TAFCR_TAMPTS */ + +/** + * @brief Set timestamp Pin + * @rmtoll TAFCR TSINSEL LL_RTC_TS_SetPin + * @param RTCx RTC Instance + * @param TSPin specifies the RTC Timestamp Pin. + * This parameter can be one of the following values: + * @arg LL_RTC_TimeStampPin_Default: RTC_AF1 is used as RTC Timestamp Pin. + * @arg LL_RTC_TimeStampPin_Pos1: RTC_AF2 is used as RTC Timestamp Pin. (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TS_SetPin(RTC_TypeDef *RTCx, uint32_t TSPin) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_TSINSEL, TSPin); +} + +/** + * @brief Get timestamp Pin + * @rmtoll TAFCR TSINSEL LL_RTC_TS_GetPin + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg LL_RTC_TimeStampPin_Default: RTC_AF1 is used as RTC Timestamp Pin. + * @arg LL_RTC_TimeStampPin_Pos1: RTC_AF2 is used as RTC Timestamp Pin. (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE uint32_t LL_RTC_TS_GetPin(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_TSINSEL)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Tamper Tamper + * @{ + */ + +/** + * @brief Enable RTC_TAMPx input detection + * @rmtoll TAFCR TAMP1E LL_RTC_TAMPER_Enable\n + * TAFCR TAMP2E LL_RTC_TAMPER_Enable\n + * @param RTCx RTC Instance + * @param Tamper This parameter can be a combination of the following values: + * @arg @ref LL_RTC_TAMPER_1 + * @arg @ref LL_RTC_TAMPER_2 (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_Enable(RTC_TypeDef *RTCx, uint32_t Tamper) +{ + SET_BIT(RTCx->TAFCR, Tamper); +} + +/** + * @brief Clear RTC_TAMPx input detection + * @rmtoll TAFCR TAMP1E LL_RTC_TAMPER_Disable\n + * TAFCR TAMP2E LL_RTC_TAMPER_Disable\n + * @param RTCx RTC Instance + * @param Tamper This parameter can be a combination of the following values: + * @arg @ref LL_RTC_TAMPER_1 + * @arg @ref LL_RTC_TAMPER_2 (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_Disable(RTC_TypeDef *RTCx, uint32_t Tamper) +{ + CLEAR_BIT(RTCx->TAFCR, Tamper); +} + +/** + * @brief Disable RTC_TAMPx pull-up disable (Disable precharge of RTC_TAMPx pins) + * @rmtoll TAFCR TAMPPUDIS LL_RTC_TAMPER_DisablePullUp + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_DisablePullUp(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPPUDIS); +} + +/** + * @brief Enable RTC_TAMPx pull-up disable ( Precharge RTC_TAMPx pins before sampling) + * @rmtoll TAFCR TAMPPUDIS LL_RTC_TAMPER_EnablePullUp + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_EnablePullUp(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPPUDIS); +} + +/** + * @brief Set RTC_TAMPx precharge duration + * @rmtoll TAFCR TAMPPRCH LL_RTC_TAMPER_SetPrecharge + * @param RTCx RTC Instance + * @param Duration This parameter can be one of the following values: + * @arg @ref LL_RTC_TAMPER_DURATION_1RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_2RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_4RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_8RTCCLK + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_SetPrecharge(RTC_TypeDef *RTCx, uint32_t Duration) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_TAMPPRCH, Duration); +} + +/** + * @brief Get RTC_TAMPx precharge duration + * @rmtoll TAFCR TAMPPRCH LL_RTC_TAMPER_GetPrecharge + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TAMPER_DURATION_1RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_2RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_4RTCCLK + * @arg @ref LL_RTC_TAMPER_DURATION_8RTCCLK + */ +__STATIC_INLINE uint32_t LL_RTC_TAMPER_GetPrecharge(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPPRCH)); +} + +/** + * @brief Set RTC_TAMPx filter count + * @rmtoll TAFCR TAMPFLT LL_RTC_TAMPER_SetFilterCount + * @param RTCx RTC Instance + * @param FilterCount This parameter can be one of the following values: + * @arg @ref LL_RTC_TAMPER_FILTER_DISABLE + * @arg @ref LL_RTC_TAMPER_FILTER_2SAMPLE + * @arg @ref LL_RTC_TAMPER_FILTER_4SAMPLE + * @arg @ref LL_RTC_TAMPER_FILTER_8SAMPLE + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_SetFilterCount(RTC_TypeDef *RTCx, uint32_t FilterCount) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_TAMPFLT, FilterCount); +} + +/** + * @brief Get RTC_TAMPx filter count + * @rmtoll TAFCR TAMPFLT LL_RTC_TAMPER_GetFilterCount + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TAMPER_FILTER_DISABLE + * @arg @ref LL_RTC_TAMPER_FILTER_2SAMPLE + * @arg @ref LL_RTC_TAMPER_FILTER_4SAMPLE + * @arg @ref LL_RTC_TAMPER_FILTER_8SAMPLE + */ +__STATIC_INLINE uint32_t LL_RTC_TAMPER_GetFilterCount(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPFLT)); +} + +/** + * @brief Set Tamper sampling frequency + * @rmtoll TAFCR TAMPFREQ LL_RTC_TAMPER_SetSamplingFreq + * @param RTCx RTC Instance + * @param SamplingFreq This parameter can be one of the following values: + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_32768 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_16384 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_8192 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_4096 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_2048 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_1024 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_512 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_256 + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_SetSamplingFreq(RTC_TypeDef *RTCx, uint32_t SamplingFreq) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_TAMPFREQ, SamplingFreq); +} + +/** + * @brief Get Tamper sampling frequency + * @rmtoll TAFCR TAMPFREQ LL_RTC_TAMPER_GetSamplingFreq + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_32768 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_16384 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_8192 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_4096 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_2048 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_1024 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_512 + * @arg @ref LL_RTC_TAMPER_SAMPLFREQDIV_256 + */ +__STATIC_INLINE uint32_t LL_RTC_TAMPER_GetSamplingFreq(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPFREQ)); +} + +/** + * @brief Enable Active level for Tamper input + * @rmtoll TAFCR TAMP1TRG LL_RTC_TAMPER_EnableActiveLevel\n + * TAFCR TAMP2TRG LL_RTC_TAMPER_EnableActiveLevel\n + * @param RTCx RTC Instance + * @param Tamper This parameter can be a combination of the following values: + * @arg @ref LL_RTC_TAMPER_ACTIVELEVEL_TAMP1 + * @arg @ref LL_RTC_TAMPER_ACTIVELEVEL_TAMP2 (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_EnableActiveLevel(RTC_TypeDef *RTCx, uint32_t Tamper) +{ + SET_BIT(RTCx->TAFCR, Tamper); +} + +/** + * @brief Disable Active level for Tamper input + * @rmtoll TAFCR TAMP1TRG LL_RTC_TAMPER_DisableActiveLevel\n + * TAFCR TAMP2TRG LL_RTC_TAMPER_DisableActiveLevel\n + * @param RTCx RTC Instance + * @param Tamper This parameter can be a combination of the following values: + * @arg @ref LL_RTC_TAMPER_ACTIVELEVEL_TAMP1 + * @arg @ref LL_RTC_TAMPER_ACTIVELEVEL_TAMP2 (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_DisableActiveLevel(RTC_TypeDef *RTCx, uint32_t Tamper) +{ + CLEAR_BIT(RTCx->TAFCR, Tamper); +} + +/** + * @brief Set Tamper Pin + * @rmtoll TAFCR TAMP1INSEL LL_RTC_TAMPER_SetPin + * @param RTCx RTC Instance + * @param TamperPin specifies the RTC Tamper Pin. + * This parameter can be one of the following values: + * @arg LL_RTC_TamperPin_Default: RTC_AF1 is used as RTC Tamper Pin. + * @arg LL_RTC_TamperPin_Pos1: RTC_AF2 is used as RTC Tamper Pin. (*) + * + * (*) value not applicable to all devices. + * @retval None + */ +__STATIC_INLINE void LL_RTC_TAMPER_SetPin(RTC_TypeDef *RTCx, uint32_t TamperPin) +{ + MODIFY_REG(RTCx->TAFCR, RTC_TAFCR_TAMP1INSEL, TamperPin); +} + +/** + * @brief Get Tamper Pin + * @rmtoll TAFCR TAMP1INSEL LL_RTC_TAMPER_GetPin + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg LL_RTC_TamperPin_Default: RTC_AF1 is used as RTC Tamper Pin. + * @arg LL_RTC_TamperPin_Pos1: RTC_AF2 is selected as RTC Tamper Pin. (*) + * + * (*) value not applicable to all devices. + * @retval None + */ + +__STATIC_INLINE uint32_t LL_RTC_TAMPER_GetPin(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->TAFCR, RTC_TAFCR_TAMP1INSEL)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Wakeup Wakeup + * @{ + */ + +/** + * @brief Enable Wakeup timer + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR WUTE LL_RTC_WAKEUP_Enable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_WAKEUP_Enable(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_WUTE); +} + +/** + * @brief Disable Wakeup timer + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR WUTE LL_RTC_WAKEUP_Disable + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_WAKEUP_Disable(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_WUTE); +} + +/** + * @brief Check if Wakeup timer is enabled or not + * @rmtoll CR WUTE LL_RTC_WAKEUP_IsEnabled + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_WAKEUP_IsEnabled(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) ? 1UL : 0UL); +} + +/** + * @brief Select Wakeup clock + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note Bit can be written only when RTC_CR WUTE bit = 0 and RTC_ISR WUTWF bit = 1 + * @rmtoll CR WUCKSEL LL_RTC_WAKEUP_SetClock + * @param RTCx RTC Instance + * @param WakeupClock This parameter can be one of the following values: + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_16 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_8 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_4 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_2 + * @arg @ref LL_RTC_WAKEUPCLOCK_CKSPRE + * @arg @ref LL_RTC_WAKEUPCLOCK_CKSPRE_WUT + * @retval None + */ +__STATIC_INLINE void LL_RTC_WAKEUP_SetClock(RTC_TypeDef *RTCx, uint32_t WakeupClock) +{ + MODIFY_REG(RTCx->CR, RTC_CR_WUCKSEL, WakeupClock); +} + +/** + * @brief Get Wakeup clock + * @rmtoll CR WUCKSEL LL_RTC_WAKEUP_GetClock + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_16 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_8 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_4 + * @arg @ref LL_RTC_WAKEUPCLOCK_DIV_2 + * @arg @ref LL_RTC_WAKEUPCLOCK_CKSPRE + * @arg @ref LL_RTC_WAKEUPCLOCK_CKSPRE_WUT + */ +__STATIC_INLINE uint32_t LL_RTC_WAKEUP_GetClock(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_WUCKSEL)); +} + +/** + * @brief Set Wakeup auto-reload value + * @note Bit can be written only when WUTWF is set to 1 in RTC_ISR + * @rmtoll WUTR WUT LL_RTC_WAKEUP_SetAutoReload + * @param RTCx RTC Instance + * @param Value Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_RTC_WAKEUP_SetAutoReload(RTC_TypeDef *RTCx, uint32_t Value) +{ + MODIFY_REG(RTCx->WUTR, RTC_WUTR_WUT, Value); +} + +/** + * @brief Get Wakeup auto-reload value + * @rmtoll WUTR WUT LL_RTC_WAKEUP_GetAutoReload + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint32_t LL_RTC_WAKEUP_GetAutoReload(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->WUTR, RTC_WUTR_WUT)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Backup_Registers Backup_Registers + * @{ + */ + +/** + * @brief Writes a data in a specified RTC Backup data register. + * @rmtoll BKPxR BKP LL_RTC_BAK_SetRegister + * @param RTCx RTC Instance + * @param BackupRegister This parameter can be one of the following values: + * @arg @ref LL_RTC_BKP_DR0 + * @arg @ref LL_RTC_BKP_DR1 + * @arg @ref LL_RTC_BKP_DR2 + * @arg @ref LL_RTC_BKP_DR3 + * @arg @ref LL_RTC_BKP_DR4 + * @arg @ref LL_RTC_BKP_DR5 + * @arg @ref LL_RTC_BKP_DR6 + * @arg @ref LL_RTC_BKP_DR7 + * @arg @ref LL_RTC_BKP_DR8 + * @arg @ref LL_RTC_BKP_DR9 + * @arg @ref LL_RTC_BKP_DR10 + * @arg @ref LL_RTC_BKP_DR11 + * @arg @ref LL_RTC_BKP_DR12 + * @arg @ref LL_RTC_BKP_DR13 + * @arg @ref LL_RTC_BKP_DR14 + * @arg @ref LL_RTC_BKP_DR15 + * @arg @ref LL_RTC_BKP_DR16 + * @arg @ref LL_RTC_BKP_DR17 + * @arg @ref LL_RTC_BKP_DR18 + * @arg @ref LL_RTC_BKP_DR19 + * @param Data Value between Min_Data=0x00 and Max_Data=0xFFFFFFFF + * @retval None + */ +__STATIC_INLINE void LL_RTC_BAK_SetRegister(RTC_TypeDef *RTCx, uint32_t BackupRegister, uint32_t Data) +{ + uint32_t temp; + + temp = (uint32_t)(&(RTCx->BKP0R)); + temp += (BackupRegister * 4U); + + /* Write the specified register */ + *(__IO uint32_t *)temp = (uint32_t)Data; +} + +/** + * @brief Reads data from the specified RTC Backup data Register. + * @rmtoll BKPxR BKP LL_RTC_BAK_GetRegister + * @param RTCx RTC Instance + * @param BackupRegister This parameter can be one of the following values: + * @arg @ref LL_RTC_BKP_DR0 + * @arg @ref LL_RTC_BKP_DR1 + * @arg @ref LL_RTC_BKP_DR2 + * @arg @ref LL_RTC_BKP_DR3 + * @arg @ref LL_RTC_BKP_DR4 + * @arg @ref LL_RTC_BKP_DR5 + * @arg @ref LL_RTC_BKP_DR6 + * @arg @ref LL_RTC_BKP_DR7 + * @arg @ref LL_RTC_BKP_DR8 + * @arg @ref LL_RTC_BKP_DR9 + * @arg @ref LL_RTC_BKP_DR10 + * @arg @ref LL_RTC_BKP_DR11 + * @arg @ref LL_RTC_BKP_DR12 + * @arg @ref LL_RTC_BKP_DR13 + * @arg @ref LL_RTC_BKP_DR14 + * @arg @ref LL_RTC_BKP_DR15 + * @arg @ref LL_RTC_BKP_DR16 + * @arg @ref LL_RTC_BKP_DR17 + * @arg @ref LL_RTC_BKP_DR18 + * @arg @ref LL_RTC_BKP_DR19 + * @retval Value between Min_Data=0x00 and Max_Data=0xFFFFFFFF + */ +__STATIC_INLINE uint32_t LL_RTC_BAK_GetRegister(RTC_TypeDef *RTCx, uint32_t BackupRegister) +{ + uint32_t temp; + + temp = (uint32_t)(&(RTCx->BKP0R)); + temp += (BackupRegister * 4U); + + /* Read the specified register */ + return (*(__IO uint32_t *)temp); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_Calibration Calibration + * @{ + */ + +/** + * @brief Set Calibration output frequency (1 Hz or 512 Hz) + * @note Bits are write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR COE LL_RTC_CAL_SetOutputFreq\n + * CR COSEL LL_RTC_CAL_SetOutputFreq + * @param RTCx RTC Instance + * @param Frequency This parameter can be one of the following values: + * @arg @ref LL_RTC_CALIB_OUTPUT_NONE + * @arg @ref LL_RTC_CALIB_OUTPUT_1HZ + * @arg @ref LL_RTC_CALIB_OUTPUT_512HZ + * + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_SetOutputFreq(RTC_TypeDef *RTCx, uint32_t Frequency) +{ + MODIFY_REG(RTCx->CR, RTC_CR_COE | RTC_CR_COSEL, Frequency); +} + +/** + * @brief Get Calibration output frequency (1 Hz or 512 Hz) + * @rmtoll CR COE LL_RTC_CAL_GetOutputFreq\n + * CR COSEL LL_RTC_CAL_GetOutputFreq + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_CALIB_OUTPUT_NONE + * @arg @ref LL_RTC_CALIB_OUTPUT_1HZ + * @arg @ref LL_RTC_CALIB_OUTPUT_512HZ + * + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_GetOutputFreq(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CR, RTC_CR_COE | RTC_CR_COSEL)); +} + +/** + * @brief Enable Coarse digital calibration + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CR DCE LL_RTC_CAL_EnableCoarseDigital + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_EnableCoarseDigital(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_DCE); +} + +/** + * @brief Disable Coarse digital calibration + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CR DCE LL_RTC_CAL_DisableCoarseDigital + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_DisableCoarseDigital(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_DCE); +} + +/** + * @brief Set the coarse digital calibration + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note It can be written in initialization mode only (@ref LL_RTC_EnableInitMode function) + * @rmtoll CALIBR DCS LL_RTC_CAL_ConfigCoarseDigital\n + * CALIBR DC LL_RTC_CAL_ConfigCoarseDigital + * @param RTCx RTC Instance + * @param Sign This parameter can be one of the following values: + * @arg @ref LL_RTC_CALIB_SIGN_POSITIVE + * @arg @ref LL_RTC_CALIB_SIGN_NEGATIVE + * @param Value value of coarse calibration expressed in ppm (coded on 5 bits) + * @note This Calibration value should be between 0 and 63 when using negative sign with a 2-ppm step. + * @note This Calibration value should be between 0 and 126 when using positive sign with a 4-ppm step. + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_ConfigCoarseDigital(RTC_TypeDef *RTCx, uint32_t Sign, uint32_t Value) +{ + MODIFY_REG(RTCx->CALIBR, RTC_CALIBR_DCS | RTC_CALIBR_DC, Sign | Value); +} + +/** + * @brief Get the coarse digital calibration value + * @rmtoll CALIBR DC LL_RTC_CAL_GetCoarseDigitalValue + * @param RTCx RTC Instance + * @retval value of coarse calibration expressed in ppm (coded on 5 bits) + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_GetCoarseDigitalValue(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CALIBR, RTC_CALIBR_DC)); +} + +/** + * @brief Get the coarse digital calibration sign + * @rmtoll CALIBR DCS LL_RTC_CAL_GetCoarseDigitalSign + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_CALIB_SIGN_POSITIVE + * @arg @ref LL_RTC_CALIB_SIGN_NEGATIVE + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_GetCoarseDigitalSign(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CALIBR, RTC_CALIBR_DCS)); +} + +/** + * @brief Insert or not One RTCCLK pulse every 2exp11 pulses (frequency increased by 488.5 ppm) + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note Bit can be written only when RECALPF is set to 0 in RTC_ISR + * @rmtoll CALR CALP LL_RTC_CAL_SetPulse + * @param RTCx RTC Instance + * @param Pulse This parameter can be one of the following values: + * @arg @ref LL_RTC_CALIB_INSERTPULSE_NONE + * @arg @ref LL_RTC_CALIB_INSERTPULSE_SET + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_SetPulse(RTC_TypeDef *RTCx, uint32_t Pulse) +{ + MODIFY_REG(RTCx->CALR, RTC_CALR_CALP, Pulse); +} + +/** + * @brief Check if one RTCCLK has been inserted or not every 2exp11 pulses (frequency increased by 488.5 ppm) + * @rmtoll CALR CALP LL_RTC_CAL_IsPulseInserted + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_IsPulseInserted(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CALR, RTC_CALR_CALP) == (RTC_CALR_CALP)) ? 1UL : 0UL); +} + +/** + * @brief Set smooth calibration cycle period + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note Bit can be written only when RECALPF is set to 0 in RTC_ISR + * @rmtoll CALR CALW8 LL_RTC_CAL_SetPeriod\n + * CALR CALW16 LL_RTC_CAL_SetPeriod + * @param RTCx RTC Instance + * @param Period This parameter can be one of the following values: + * @arg @ref LL_RTC_CALIB_PERIOD_32SEC + * @arg @ref LL_RTC_CALIB_PERIOD_16SEC + * @arg @ref LL_RTC_CALIB_PERIOD_8SEC + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_SetPeriod(RTC_TypeDef *RTCx, uint32_t Period) +{ + MODIFY_REG(RTCx->CALR, RTC_CALR_CALW8 | RTC_CALR_CALW16, Period); +} + +/** + * @brief Get smooth calibration cycle period + * @rmtoll CALR CALW8 LL_RTC_CAL_GetPeriod\n + * CALR CALW16 LL_RTC_CAL_GetPeriod + * @param RTCx RTC Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_RTC_CALIB_PERIOD_32SEC + * @arg @ref LL_RTC_CALIB_PERIOD_16SEC + * @arg @ref LL_RTC_CALIB_PERIOD_8SEC + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_GetPeriod(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CALR, RTC_CALR_CALW8 | RTC_CALR_CALW16)); +} + +/** + * @brief Set smooth Calibration minus + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @note Bit can be written only when RECALPF is set to 0 in RTC_ISR + * @rmtoll CALR CALM LL_RTC_CAL_SetMinus + * @param RTCx RTC Instance + * @param CalibMinus Value between Min_Data=0x00 and Max_Data=0x1FF + * @retval None + */ +__STATIC_INLINE void LL_RTC_CAL_SetMinus(RTC_TypeDef *RTCx, uint32_t CalibMinus) +{ + MODIFY_REG(RTCx->CALR, RTC_CALR_CALM, CalibMinus); +} + +/** + * @brief Get smooth Calibration minus + * @rmtoll CALR CALM LL_RTC_CAL_GetMinus + * @param RTCx RTC Instance + * @retval Value between Min_Data=0x00 and Max_Data= 0x1FF + */ +__STATIC_INLINE uint32_t LL_RTC_CAL_GetMinus(RTC_TypeDef *RTCx) +{ + return (uint32_t)(READ_BIT(RTCx->CALR, RTC_CALR_CALM)); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_FLAG_Management FLAG_Management + * @{ + */ + +/** + * @brief Get Recalibration pending Flag + * @rmtoll ISR RECALPF LL_RTC_IsActiveFlag_RECALP + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_RECALP(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_RECALPF) == (RTC_ISR_RECALPF)) ? 1UL : 0UL); +} + +#if defined(RTC_TAMPER2_SUPPORT) +/** + * @brief Get RTC_TAMP2 detection flag + * @rmtoll ISR TAMP2F LL_RTC_IsActiveFlag_TAMP2 + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_TAMP2(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_TAMP2F) == (RTC_ISR_TAMP2F)) ? 1UL : 0UL); +} +#endif /* RTC_TAMPER2_SUPPORT */ + +/** + * @brief Get RTC_TAMP1 detection flag + * @rmtoll ISR TAMP1F LL_RTC_IsActiveFlag_TAMP1 + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_TAMP1(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_TAMP1F) == (RTC_ISR_TAMP1F)) ? 1UL : 0UL); +} + +/** + * @brief Get Time-stamp overflow flag + * @rmtoll ISR TSOVF LL_RTC_IsActiveFlag_TSOV + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_TSOV(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_TSOVF) == (RTC_ISR_TSOVF)) ? 1UL : 0UL); +} + +/** + * @brief Get Time-stamp flag + * @rmtoll ISR TSF LL_RTC_IsActiveFlag_TS + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_TS(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_TSF) == (RTC_ISR_TSF)) ? 1UL : 0UL); +} + +/** + * @brief Get Wakeup timer flag + * @rmtoll ISR WUTF LL_RTC_IsActiveFlag_WUT + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_WUT(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_WUTF) == (RTC_ISR_WUTF)) ? 1UL : 0UL); +} + +/** + * @brief Get Alarm B flag + * @rmtoll ISR ALRBF LL_RTC_IsActiveFlag_ALRB + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_ALRB(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_ALRBF) == (RTC_ISR_ALRBF)) ? 1UL : 0UL); +} + +/** + * @brief Get Alarm A flag + * @rmtoll ISR ALRAF LL_RTC_IsActiveFlag_ALRA + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_ALRA(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_ALRAF) == (RTC_ISR_ALRAF)) ? 1UL : 0UL); +} + +#if defined(RTC_TAMPER2_SUPPORT) +/** + * @brief Clear RTC_TAMP2 detection flag + * @rmtoll ISR TAMP2F LL_RTC_ClearFlag_TAMP2 + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_TAMP2(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_TAMP2F | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} +#endif /* RTC_TAMPER2_SUPPORT */ + +/** + * @brief Clear RTC_TAMP1 detection flag + * @rmtoll ISR TAMP1F LL_RTC_ClearFlag_TAMP1 + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_TAMP1(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_TAMP1F | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Clear Time-stamp overflow flag + * @rmtoll ISR TSOVF LL_RTC_ClearFlag_TSOV + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_TSOV(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_TSOVF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Clear Time-stamp flag + * @rmtoll ISR TSF LL_RTC_ClearFlag_TS + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_TS(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_TSF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Clear Wakeup timer flag + * @rmtoll ISR WUTF LL_RTC_ClearFlag_WUT + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_WUT(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_WUTF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Clear Alarm B flag + * @rmtoll ISR ALRBF LL_RTC_ClearFlag_ALRB + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_ALRB(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_ALRBF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Clear Alarm A flag + * @rmtoll ISR ALRAF LL_RTC_ClearFlag_ALRA + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_ALRA(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_ALRAF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Get Initialization flag + * @rmtoll ISR INITF LL_RTC_IsActiveFlag_INIT + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_INIT(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_INITF) == (RTC_ISR_INITF)) ? 1UL : 0UL); +} + +/** + * @brief Get Registers synchronization flag + * @rmtoll ISR RSF LL_RTC_IsActiveFlag_RS + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_RS(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_RSF) == (RTC_ISR_RSF)) ? 1UL : 0UL); +} + +/** + * @brief Clear Registers synchronization flag + * @rmtoll ISR RSF LL_RTC_ClearFlag_RS + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_ClearFlag_RS(RTC_TypeDef *RTCx) +{ + WRITE_REG(RTCx->ISR, (~((RTC_ISR_RSF | RTC_ISR_INIT) & 0x0000FFFFU) | (RTCx->ISR & RTC_ISR_INIT))); +} + +/** + * @brief Get Initialization status flag + * @rmtoll ISR INITS LL_RTC_IsActiveFlag_INITS + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_INITS(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_INITS) == (RTC_ISR_INITS)) ? 1UL : 0UL); +} + +/** + * @brief Get Shift operation pending flag + * @rmtoll ISR SHPF LL_RTC_IsActiveFlag_SHP + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_SHP(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_SHPF) == (RTC_ISR_SHPF)) ? 1UL : 0UL); +} + +/** + * @brief Get Wakeup timer write flag + * @rmtoll ISR WUTWF LL_RTC_IsActiveFlag_WUTW + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_WUTW(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_WUTWF) == (RTC_ISR_WUTWF)) ? 1UL : 0UL); +} + +/** + * @brief Get Alarm B write flag + * @rmtoll ISR ALRBWF LL_RTC_IsActiveFlag_ALRBW + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_ALRBW(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_ALRBWF) == (RTC_ISR_ALRBWF)) ? 1UL : 0UL); +} + +/** + * @brief Get Alarm A write flag + * @rmtoll ISR ALRAWF LL_RTC_IsActiveFlag_ALRAW + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsActiveFlag_ALRAW(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->ISR, RTC_ISR_ALRAWF) == (RTC_ISR_ALRAWF)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup RTC_LL_EF_IT_Management IT_Management + * @{ + */ + +/** + * @brief Enable Time-stamp interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR TSIE LL_RTC_EnableIT_TS + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableIT_TS(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_TSIE); +} + +/** + * @brief Disable Time-stamp interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR TSIE LL_RTC_DisableIT_TS + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableIT_TS(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_TSIE); +} + +/** + * @brief Enable Wakeup timer interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR WUTIE LL_RTC_EnableIT_WUT + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableIT_WUT(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_WUTIE); +} + +/** + * @brief Disable Wakeup timer interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR WUTIE LL_RTC_DisableIT_WUT + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableIT_WUT(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_WUTIE); +} + +/** + * @brief Enable Alarm B interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRBIE LL_RTC_EnableIT_ALRB + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableIT_ALRB(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_ALRBIE); +} + +/** + * @brief Disable Alarm B interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRBIE LL_RTC_DisableIT_ALRB + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableIT_ALRB(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_ALRBIE); +} + +/** + * @brief Enable Alarm A interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRAIE LL_RTC_EnableIT_ALRA + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableIT_ALRA(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->CR, RTC_CR_ALRAIE); +} + +/** + * @brief Disable Alarm A interrupt + * @note Bit is write-protected. @ref LL_RTC_DisableWriteProtection function should be called before. + * @rmtoll CR ALRAIE LL_RTC_DisableIT_ALRA + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableIT_ALRA(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->CR, RTC_CR_ALRAIE); +} + +/** + * @brief Enable all Tamper Interrupt + * @rmtoll TAFCR TAMPIE LL_RTC_EnableIT_TAMP + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_EnableIT_TAMP(RTC_TypeDef *RTCx) +{ + SET_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPIE); +} + +/** + * @brief Disable all Tamper Interrupt + * @rmtoll TAFCR TAMPIE LL_RTC_DisableIT_TAMP + * @param RTCx RTC Instance + * @retval None + */ +__STATIC_INLINE void LL_RTC_DisableIT_TAMP(RTC_TypeDef *RTCx) +{ + CLEAR_BIT(RTCx->TAFCR, RTC_TAFCR_TAMPIE); +} + +/** + * @brief Check if Time-stamp interrupt is enabled or not + * @rmtoll CR TSIE LL_RTC_IsEnabledIT_TS + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsEnabledIT_TS(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_TSIE) == (RTC_CR_TSIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Wakeup timer interrupt is enabled or not + * @rmtoll CR WUTIE LL_RTC_IsEnabledIT_WUT + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsEnabledIT_WUT(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_WUTIE) == (RTC_CR_WUTIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Alarm B interrupt is enabled or not + * @rmtoll CR ALRBIE LL_RTC_IsEnabledIT_ALRB + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsEnabledIT_ALRB(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_ALRBIE) == (RTC_CR_ALRBIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Alarm A interrupt is enabled or not + * @rmtoll CR ALRAIE LL_RTC_IsEnabledIT_ALRA + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsEnabledIT_ALRA(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->CR, RTC_CR_ALRAIE) == (RTC_CR_ALRAIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if all the TAMPER interrupts are enabled or not + * @rmtoll TAFCR TAMPIE LL_RTC_IsEnabledIT_TAMP + * @param RTCx RTC Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_RTC_IsEnabledIT_TAMP(RTC_TypeDef *RTCx) +{ + return ((READ_BIT(RTCx->TAFCR, + RTC_TAFCR_TAMPIE) == (RTC_TAFCR_TAMPIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup RTC_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_RTC_DeInit(RTC_TypeDef *RTCx); +ErrorStatus LL_RTC_Init(RTC_TypeDef *RTCx, LL_RTC_InitTypeDef *RTC_InitStruct); +void LL_RTC_StructInit(LL_RTC_InitTypeDef *RTC_InitStruct); +ErrorStatus LL_RTC_TIME_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_TimeTypeDef *RTC_TimeStruct); +void LL_RTC_TIME_StructInit(LL_RTC_TimeTypeDef *RTC_TimeStruct); +ErrorStatus LL_RTC_DATE_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_DateTypeDef *RTC_DateStruct); +void LL_RTC_DATE_StructInit(LL_RTC_DateTypeDef *RTC_DateStruct); +ErrorStatus LL_RTC_ALMA_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct); +ErrorStatus LL_RTC_ALMB_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct); +void LL_RTC_ALMA_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct); +void LL_RTC_ALMB_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct); +ErrorStatus LL_RTC_EnterInitMode(RTC_TypeDef *RTCx); +ErrorStatus LL_RTC_ExitInitMode(RTC_TypeDef *RTCx); +ErrorStatus LL_RTC_WaitForSynchro(RTC_TypeDef *RTCx); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RTC) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_RTC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h new file mode 100644 index 0000000..a4092d0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_sdmmc.h @@ -0,0 +1,1141 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_sdmmc.h + * @author MCD Application Team + * @brief Header file of SDMMC 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 STM32F4xx_LL_SDMMC_H +#define STM32F4xx_LL_SDMMC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(SDIO) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +/** @addtogroup STM32F4xx_Driver + * @{ + */ + +/** @addtogroup SDMMC_LL + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup SDMMC_LL_Exported_Types SDMMC_LL Exported Types + * @{ + */ + +/** + * @brief SDMMC Configuration Structure definition + */ +typedef struct +{ + uint32_t ClockEdge; /*!< Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SDMMC_LL_Clock_Edge */ + + uint32_t ClockBypass; /*!< Specifies whether the SDMMC Clock divider bypass is + enabled or disabled. + This parameter can be a value of @ref SDMMC_LL_Clock_Bypass */ + + uint32_t ClockPowerSave; /*!< Specifies whether SDMMC Clock output is enabled or + disabled when the bus is idle. + This parameter can be a value of @ref SDMMC_LL_Clock_Power_Save */ + + uint32_t BusWide; /*!< Specifies the SDMMC bus width. + This parameter can be a value of @ref SDMMC_LL_Bus_Wide */ + + uint32_t HardwareFlowControl; /*!< Specifies whether the SDMMC hardware flow control is enabled or disabled. + This parameter can be a value of @ref SDMMC_LL_Hardware_Flow_Control */ + + uint32_t ClockDiv; /*!< Specifies the clock frequency of the SDMMC controller. + This parameter can be a value between Min_Data = 0 and Max_Data = 255 */ + +}SDIO_InitTypeDef; + + +/** + * @brief SDMMC Command Control structure + */ +typedef struct +{ + uint32_t Argument; /*!< Specifies the SDMMC command argument which is sent + to a card as part of a command message. If a command + contains an argument, it must be loaded into this register + before writing the command to the command register. */ + + uint32_t CmdIndex; /*!< Specifies the SDMMC command index. It must be Min_Data = 0 and + Max_Data = 64 */ + + uint32_t Response; /*!< Specifies the SDMMC response type. + This parameter can be a value of @ref SDMMC_LL_Response_Type */ + + uint32_t WaitForInterrupt; /*!< Specifies whether SDMMC wait for interrupt request is + enabled or disabled. + This parameter can be a value of @ref SDMMC_LL_Wait_Interrupt_State */ + + uint32_t CPSM; /*!< Specifies whether SDMMC Command path state machine (CPSM) + is enabled or disabled. + This parameter can be a value of @ref SDMMC_LL_CPSM_State */ +}SDIO_CmdInitTypeDef; + + +/** + * @brief SDMMC Data Control structure + */ +typedef struct +{ + uint32_t DataTimeOut; /*!< Specifies the data timeout period in card bus clock periods. */ + + uint32_t DataLength; /*!< Specifies the number of data bytes to be transferred. */ + + uint32_t DataBlockSize; /*!< Specifies the data block size for block transfer. + This parameter can be a value of @ref SDMMC_LL_Data_Block_Size */ + + uint32_t TransferDir; /*!< Specifies the data transfer direction, whether the transfer + is a read or write. + This parameter can be a value of @ref SDMMC_LL_Transfer_Direction */ + + uint32_t TransferMode; /*!< Specifies whether data transfer is in stream or block mode. + This parameter can be a value of @ref SDMMC_LL_Transfer_Type */ + + uint32_t DPSM; /*!< Specifies whether SDMMC Data path state machine (DPSM) + is enabled or disabled. + This parameter can be a value of @ref SDMMC_LL_DPSM_State */ +}SDIO_DataInitTypeDef; + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SDMMC_LL_Exported_Constants SDMMC_LL Exported Constants + * @{ + */ +#define SDMMC_ERROR_NONE 0x00000000U /*!< No error */ +#define SDMMC_ERROR_CMD_CRC_FAIL 0x00000001U /*!< Command response received (but CRC check failed) */ +#define SDMMC_ERROR_DATA_CRC_FAIL 0x00000002U /*!< Data block sent/received (CRC check failed) */ +#define SDMMC_ERROR_CMD_RSP_TIMEOUT 0x00000004U /*!< Command response timeout */ +#define SDMMC_ERROR_DATA_TIMEOUT 0x00000008U /*!< Data timeout */ +#define SDMMC_ERROR_TX_UNDERRUN 0x00000010U /*!< Transmit FIFO underrun */ +#define SDMMC_ERROR_RX_OVERRUN 0x00000020U /*!< Receive FIFO overrun */ +#define SDMMC_ERROR_ADDR_MISALIGNED 0x00000040U /*!< Misaligned address */ +#define SDMMC_ERROR_BLOCK_LEN_ERR 0x00000080U /*!< Transferred block length is not allowed for the card or the + number of transferred bytes does not match the block length */ +#define SDMMC_ERROR_ERASE_SEQ_ERR 0x00000100U /*!< An error in the sequence of erase command occurs */ +#define SDMMC_ERROR_BAD_ERASE_PARAM 0x00000200U /*!< An invalid selection for erase groups */ +#define SDMMC_ERROR_WRITE_PROT_VIOLATION 0x00000400U /*!< Attempt to program a write protect block */ +#define SDMMC_ERROR_LOCK_UNLOCK_FAILED 0x00000800U /*!< Sequence or password error has been detected in unlock + command or if there was an attempt to access a locked card */ +#define SDMMC_ERROR_COM_CRC_FAILED 0x00001000U /*!< CRC check of the previous command failed */ +#define SDMMC_ERROR_ILLEGAL_CMD 0x00002000U /*!< Command is not legal for the card state */ +#define SDMMC_ERROR_CARD_ECC_FAILED 0x00004000U /*!< Card internal ECC was applied but failed to correct the data */ +#define SDMMC_ERROR_CC_ERR 0x00008000U /*!< Internal card controller error */ +#define SDMMC_ERROR_GENERAL_UNKNOWN_ERR 0x00010000U /*!< General or unknown error */ +#define SDMMC_ERROR_STREAM_READ_UNDERRUN 0x00020000U /*!< The card could not sustain data reading in stream rmode */ +#define SDMMC_ERROR_STREAM_WRITE_OVERRUN 0x00040000U /*!< The card could not sustain data programming in stream mode */ +#define SDMMC_ERROR_CID_CSD_OVERWRITE 0x00080000U /*!< CID/CSD overwrite error */ +#define SDMMC_ERROR_WP_ERASE_SKIP 0x00100000U /*!< Only partial address space was erased */ +#define SDMMC_ERROR_CARD_ECC_DISABLED 0x00200000U /*!< Command has been executed without using internal ECC */ +#define SDMMC_ERROR_ERASE_RESET 0x00400000U /*!< Erase sequence was cleared before executing because an out + of erase sequence command was received */ +#define SDMMC_ERROR_AKE_SEQ_ERR 0x00800000U /*!< Error in sequence of authentication */ +#define SDMMC_ERROR_INVALID_VOLTRANGE 0x01000000U /*!< Error in case of invalid voltage range */ +#define SDMMC_ERROR_ADDR_OUT_OF_RANGE 0x02000000U /*!< Error when addressed block is out of range */ +#define SDMMC_ERROR_REQUEST_NOT_APPLICABLE 0x04000000U /*!< Error when command request is not applicable */ +#define SDMMC_ERROR_INVALID_PARAMETER 0x08000000U /*!< the used parameter is not valid */ +#define SDMMC_ERROR_UNSUPPORTED_FEATURE 0x10000000U /*!< Error when feature is not insupported */ +#define SDMMC_ERROR_BUSY 0x20000000U /*!< Error when transfer process is busy */ +#define SDMMC_ERROR_DMA 0x40000000U /*!< Error while DMA transfer */ +#define SDMMC_ERROR_TIMEOUT 0x80000000U /*!< Timeout error */ + +/** + * @brief SDMMC Commands Index + */ +#define SDMMC_CMD_GO_IDLE_STATE 0U /*!< Resets the SD memory card. */ +#define SDMMC_CMD_SEND_OP_COND 1U /*!< Sends host capacity support information and activates the card's initialization process. */ +#define SDMMC_CMD_ALL_SEND_CID 2U /*!< Asks any card connected to the host to send the CID numbers on the CMD line. */ +#define SDMMC_CMD_SET_REL_ADDR 3U /*!< Asks the card to publish a new relative address (RCA). */ +#define SDMMC_CMD_SET_DSR 4U /*!< Programs the DSR of all cards. */ +#define SDMMC_CMD_SDMMC_SEN_OP_COND 5U /*!< Sends host capacity support information (HCS) and asks the accessed card to send its + operating condition register (OCR) content in the response on the CMD line. */ +#define SDMMC_CMD_HS_SWITCH 6U /*!< Checks switchable function (mode 0) and switch card function (mode 1). */ +#define SDMMC_CMD_SEL_DESEL_CARD 7U /*!< Selects the card by its own relative address and gets deselected by any other address */ +#define SDMMC_CMD_HS_SEND_EXT_CSD 8U /*!< Sends SD Memory Card interface condition, which includes host supply voltage information + and asks the card whether card supports voltage. */ +#define SDMMC_CMD_SEND_CSD 9U /*!< Addressed card sends its card specific data (CSD) on the CMD line. */ +#define SDMMC_CMD_SEND_CID 10U /*!< Addressed card sends its card identification (CID) on the CMD line. */ +#define SDMMC_CMD_READ_DAT_UNTIL_STOP 11U /*!< SD card doesn't support it. */ +#define SDMMC_CMD_STOP_TRANSMISSION 12U /*!< Forces the card to stop transmission. */ +#define SDMMC_CMD_SEND_STATUS 13U /*!< Addressed card sends its status register. */ +#define SDMMC_CMD_HS_BUSTEST_READ 14U /*!< Reserved */ +#define SDMMC_CMD_GO_INACTIVE_STATE 15U /*!< Sends an addressed card into the inactive state. */ +#define SDMMC_CMD_SET_BLOCKLEN 16U /*!< Sets the block length (in bytes for SDSC) for all following block commands + (read, write, lock). Default block length is fixed to 512 Bytes. Not effective + for SDHS and SDXC. */ +#define SDMMC_CMD_READ_SINGLE_BLOCK 17U /*!< Reads single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of + fixed 512 bytes in case of SDHC and SDXC. */ +#define SDMMC_CMD_READ_MULT_BLOCK 18U /*!< Continuously transfers data blocks from card to host until interrupted by + STOP_TRANSMISSION command. */ +#define SDMMC_CMD_HS_BUSTEST_WRITE 19U /*!< 64 bytes tuning pattern is sent for SDR50 and SDR104. */ +#define SDMMC_CMD_WRITE_DAT_UNTIL_STOP 20U /*!< Speed class control command. */ +#define SDMMC_CMD_SET_BLOCK_COUNT 23U /*!< Specify block count for CMD18 and CMD25. */ +#define SDMMC_CMD_WRITE_SINGLE_BLOCK 24U /*!< Writes single block of size selected by SET_BLOCKLEN in case of SDSC, and a block of + fixed 512 bytes in case of SDHC and SDXC. */ +#define SDMMC_CMD_WRITE_MULT_BLOCK 25U /*!< Continuously writes blocks of data until a STOP_TRANSMISSION follows. */ +#define SDMMC_CMD_PROG_CID 26U /*!< Reserved for manufacturers. */ +#define SDMMC_CMD_PROG_CSD 27U /*!< Programming of the programmable bits of the CSD. */ +#define SDMMC_CMD_SET_WRITE_PROT 28U /*!< Sets the write protection bit of the addressed group. */ +#define SDMMC_CMD_CLR_WRITE_PROT 29U /*!< Clears the write protection bit of the addressed group. */ +#define SDMMC_CMD_SEND_WRITE_PROT 30U /*!< Asks the card to send the status of the write protection bits. */ +#define SDMMC_CMD_SD_ERASE_GRP_START 32U /*!< Sets the address of the first write block to be erased. (For SD card only). */ +#define SDMMC_CMD_SD_ERASE_GRP_END 33U /*!< Sets the address of the last write block of the continuous range to be erased. */ +#define SDMMC_CMD_ERASE_GRP_START 35U /*!< Sets the address of the first write block to be erased. Reserved for each command + system set by switch function command (CMD6). */ +#define SDMMC_CMD_ERASE_GRP_END 36U /*!< Sets the address of the last write block of the continuous range to be erased. + Reserved for each command system set by switch function command (CMD6). */ +#define SDMMC_CMD_ERASE 38U /*!< Reserved for SD security applications. */ +#define SDMMC_CMD_FAST_IO 39U /*!< SD card doesn't support it (Reserved). */ +#define SDMMC_CMD_GO_IRQ_STATE 40U /*!< SD card doesn't support it (Reserved). */ +#define SDMMC_CMD_LOCK_UNLOCK 42U /*!< Sets/resets the password or lock/unlock the card. The size of the data block is set by + the SET_BLOCK_LEN command. */ +#define SDMMC_CMD_APP_CMD 55U /*!< Indicates to the card that the next command is an application specific command rather + than a standard command. */ +#define SDMMC_CMD_GEN_CMD 56U /*!< Used either to transfer a data block to the card or to get a data block from the card + for general purpose/application specific commands. */ +#define SDMMC_CMD_NO_CMD 64U /*!< No command */ + +/** + * @brief Following commands are SD Card Specific commands. + * SDMMC_APP_CMD should be sent before sending these commands. + */ +#define SDMMC_CMD_APP_SD_SET_BUSWIDTH 6U /*!< (ACMD6) Defines the data bus width to be used for data transfer. The allowed data bus + widths are given in SCR register. */ +#define SDMMC_CMD_SD_APP_STATUS 13U /*!< (ACMD13) Sends the SD status. */ +#define SDMMC_CMD_SD_APP_SEND_NUM_WRITE_BLOCKS 22U /*!< (ACMD22) Sends the number of the written (without errors) write blocks. Responds with + 32bit+CRC data block. */ +#define SDMMC_CMD_SD_APP_OP_COND 41U /*!< (ACMD41) Sends host capacity support information (HCS) and asks the accessed card to + send its operating condition register (OCR) content in the response on the CMD line. */ +#define SDMMC_CMD_SD_APP_SET_CLR_CARD_DETECT 42U /*!< (ACMD42) Connect/Disconnect the 50 KOhm pull-up resistor on CD/DAT3 (pin 1) of the card */ +#define SDMMC_CMD_SD_APP_SEND_SCR 51U /*!< Reads the SD Configuration Register (SCR). */ +#define SDMMC_CMD_SDMMC_RW_DIRECT 52U /*!< For SD I/O card only, reserved for security specification. */ +#define SDMMC_CMD_SDMMC_RW_EXTENDED 53U /*!< For SD I/O card only, reserved for security specification. */ + +/** + * @brief Following commands are SD Card Specific security commands. + * SDMMC_CMD_APP_CMD should be sent before sending these commands. + */ +#define SDMMC_CMD_SD_APP_GET_MKB 43U +#define SDMMC_CMD_SD_APP_GET_MID 44U +#define SDMMC_CMD_SD_APP_SET_CER_RN1 45U +#define SDMMC_CMD_SD_APP_GET_CER_RN2 46U +#define SDMMC_CMD_SD_APP_SET_CER_RES2 47U +#define SDMMC_CMD_SD_APP_GET_CER_RES1 48U +#define SDMMC_CMD_SD_APP_SECURE_READ_MULTIPLE_BLOCK 18U +#define SDMMC_CMD_SD_APP_SECURE_WRITE_MULTIPLE_BLOCK 25U +#define SDMMC_CMD_SD_APP_SECURE_ERASE 38U +#define SDMMC_CMD_SD_APP_CHANGE_SECURE_AREA 49U +#define SDMMC_CMD_SD_APP_SECURE_WRITE_MKB 48U + +/** + * @brief Masks for errors Card Status R1 (OCR Register) + */ +#define SDMMC_OCR_ADDR_OUT_OF_RANGE 0x80000000U +#define SDMMC_OCR_ADDR_MISALIGNED 0x40000000U +#define SDMMC_OCR_BLOCK_LEN_ERR 0x20000000U +#define SDMMC_OCR_ERASE_SEQ_ERR 0x10000000U +#define SDMMC_OCR_BAD_ERASE_PARAM 0x08000000U +#define SDMMC_OCR_WRITE_PROT_VIOLATION 0x04000000U +#define SDMMC_OCR_LOCK_UNLOCK_FAILED 0x01000000U +#define SDMMC_OCR_COM_CRC_FAILED 0x00800000U +#define SDMMC_OCR_ILLEGAL_CMD 0x00400000U +#define SDMMC_OCR_CARD_ECC_FAILED 0x00200000U +#define SDMMC_OCR_CC_ERROR 0x00100000U +#define SDMMC_OCR_GENERAL_UNKNOWN_ERROR 0x00080000U +#define SDMMC_OCR_STREAM_READ_UNDERRUN 0x00040000U +#define SDMMC_OCR_STREAM_WRITE_OVERRUN 0x00020000U +#define SDMMC_OCR_CID_CSD_OVERWRITE 0x00010000U +#define SDMMC_OCR_WP_ERASE_SKIP 0x00008000U +#define SDMMC_OCR_CARD_ECC_DISABLED 0x00004000U +#define SDMMC_OCR_ERASE_RESET 0x00002000U +#define SDMMC_OCR_AKE_SEQ_ERROR 0x00000008U +#define SDMMC_OCR_ERRORBITS 0xFDFFE008U + +/** + * @brief Masks for R6 Response + */ +#define SDMMC_R6_GENERAL_UNKNOWN_ERROR 0x00002000U +#define SDMMC_R6_ILLEGAL_CMD 0x00004000U +#define SDMMC_R6_COM_CRC_FAILED 0x00008000U + +#define SDMMC_VOLTAGE_WINDOW_SD 0x80100000U +#define SDMMC_HIGH_CAPACITY 0x40000000U +#define SDMMC_STD_CAPACITY 0x00000000U +#define SDMMC_CHECK_PATTERN 0x000001AAU +#define SD_SWITCH_1_8V_CAPACITY 0x01000000U + +#define SDMMC_MAX_VOLT_TRIAL 0x0000FFFFU + +#define SDMMC_MAX_TRIAL 0x0000FFFFU + +#define SDMMC_ALLZERO 0x00000000U + +#define SDMMC_WIDE_BUS_SUPPORT 0x00040000U +#define SDMMC_SINGLE_BUS_SUPPORT 0x00010000U +#define SDMMC_CARD_LOCKED 0x02000000U + +#ifndef SDMMC_DATATIMEOUT +#define SDMMC_DATATIMEOUT 0xFFFFFFFFU +#endif /* SDMMC_DATATIMEOUT */ + +#define SDMMC_0TO7BITS 0x000000FFU +#define SDMMC_8TO15BITS 0x0000FF00U +#define SDMMC_16TO23BITS 0x00FF0000U +#define SDMMC_24TO31BITS 0xFF000000U +#define SDMMC_MAX_DATA_LENGTH 0x01FFFFFFU + +#define SDMMC_HALFFIFO 0x00000008U +#define SDMMC_HALFFIFOBYTES 0x00000020U + +/** + * @brief Command Class supported + */ +#define SDIO_CCCC_ERASE 0x00000020U + +#define SDIO_CMDTIMEOUT 5000U /* Command send and response timeout */ +#define SDIO_MAXERASETIMEOUT 63000U /* Max erase Timeout 63 s */ +#define SDIO_STOPTRANSFERTIMEOUT 100000000U /* Timeout for STOP TRANSMISSION command */ + +/** @defgroup SDIO_LL_Clock_Edge Clock Edge + * @{ + */ +#define SDIO_CLOCK_EDGE_RISING 0x00000000U +#define SDIO_CLOCK_EDGE_FALLING SDIO_CLKCR_NEGEDGE + +#define IS_SDIO_CLOCK_EDGE(EDGE) (((EDGE) == SDIO_CLOCK_EDGE_RISING) || \ + ((EDGE) == SDIO_CLOCK_EDGE_FALLING)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Clock_Bypass Clock Bypass + * @{ + */ +#define SDIO_CLOCK_BYPASS_DISABLE 0x00000000U +#define SDIO_CLOCK_BYPASS_ENABLE SDIO_CLKCR_BYPASS + +#define IS_SDIO_CLOCK_BYPASS(BYPASS) (((BYPASS) == SDIO_CLOCK_BYPASS_DISABLE) || \ + ((BYPASS) == SDIO_CLOCK_BYPASS_ENABLE)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Clock_Power_Save Clock Power Saving + * @{ + */ +#define SDIO_CLOCK_POWER_SAVE_DISABLE 0x00000000U +#define SDIO_CLOCK_POWER_SAVE_ENABLE SDIO_CLKCR_PWRSAV + +#define IS_SDIO_CLOCK_POWER_SAVE(SAVE) (((SAVE) == SDIO_CLOCK_POWER_SAVE_DISABLE) || \ + ((SAVE) == SDIO_CLOCK_POWER_SAVE_ENABLE)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Bus_Wide Bus Width + * @{ + */ +#define SDIO_BUS_WIDE_1B 0x00000000U +#define SDIO_BUS_WIDE_4B SDIO_CLKCR_WIDBUS_0 +#define SDIO_BUS_WIDE_8B SDIO_CLKCR_WIDBUS_1 + +#define IS_SDIO_BUS_WIDE(WIDE) (((WIDE) == SDIO_BUS_WIDE_1B) || \ + ((WIDE) == SDIO_BUS_WIDE_4B) || \ + ((WIDE) == SDIO_BUS_WIDE_8B)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Hardware_Flow_Control Hardware Flow Control + * @{ + */ +#define SDIO_HARDWARE_FLOW_CONTROL_DISABLE 0x00000000U +#define SDIO_HARDWARE_FLOW_CONTROL_ENABLE SDIO_CLKCR_HWFC_EN + +#define IS_SDIO_HARDWARE_FLOW_CONTROL(CONTROL) (((CONTROL) == SDIO_HARDWARE_FLOW_CONTROL_DISABLE) || \ + ((CONTROL) == SDIO_HARDWARE_FLOW_CONTROL_ENABLE)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Clock_Division Clock Division + * @{ + */ +#define IS_SDIO_CLKDIV(DIV) ((DIV) <= 0xFFU) +/** + * @} + */ + +/** @defgroup SDIO_LL_Command_Index Command Index + * @{ + */ +#define IS_SDIO_CMD_INDEX(INDEX) ((INDEX) < 0x40U) +/** + * @} + */ + +/** @defgroup SDIO_LL_Response_Type Response Type + * @{ + */ +#define SDIO_RESPONSE_NO 0x00000000U +#define SDIO_RESPONSE_SHORT SDIO_CMD_WAITRESP_0 +#define SDIO_RESPONSE_LONG SDIO_CMD_WAITRESP + +#define IS_SDIO_RESPONSE(RESPONSE) (((RESPONSE) == SDIO_RESPONSE_NO) || \ + ((RESPONSE) == SDIO_RESPONSE_SHORT) || \ + ((RESPONSE) == SDIO_RESPONSE_LONG)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Wait_Interrupt_State Wait Interrupt + * @{ + */ +#define SDIO_WAIT_NO 0x00000000U +#define SDIO_WAIT_IT SDIO_CMD_WAITINT +#define SDIO_WAIT_PEND SDIO_CMD_WAITPEND + +#define IS_SDIO_WAIT(WAIT) (((WAIT) == SDIO_WAIT_NO) || \ + ((WAIT) == SDIO_WAIT_IT) || \ + ((WAIT) == SDIO_WAIT_PEND)) +/** + * @} + */ + +/** @defgroup SDIO_LL_CPSM_State CPSM State + * @{ + */ +#define SDIO_CPSM_DISABLE 0x00000000U +#define SDIO_CPSM_ENABLE SDIO_CMD_CPSMEN + +#define IS_SDIO_CPSM(CPSM) (((CPSM) == SDIO_CPSM_DISABLE) || \ + ((CPSM) == SDIO_CPSM_ENABLE)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Response_Registers Response Register + * @{ + */ +#define SDIO_RESP1 0x00000000U +#define SDIO_RESP2 0x00000004U +#define SDIO_RESP3 0x00000008U +#define SDIO_RESP4 0x0000000CU + +#define IS_SDIO_RESP(RESP) (((RESP) == SDIO_RESP1) || \ + ((RESP) == SDIO_RESP2) || \ + ((RESP) == SDIO_RESP3) || \ + ((RESP) == SDIO_RESP4)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Data_Length Data Length + * @{ + */ +#define IS_SDIO_DATA_LENGTH(LENGTH) ((LENGTH) <= 0x01FFFFFFU) +/** + * @} + */ + +/** @defgroup SDIO_LL_Data_Block_Size Data Block Size + * @{ + */ +#define SDIO_DATABLOCK_SIZE_1B 0x00000000U +#define SDIO_DATABLOCK_SIZE_2B SDIO_DCTRL_DBLOCKSIZE_0 +#define SDIO_DATABLOCK_SIZE_4B SDIO_DCTRL_DBLOCKSIZE_1 +#define SDIO_DATABLOCK_SIZE_8B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_1) +#define SDIO_DATABLOCK_SIZE_16B SDIO_DCTRL_DBLOCKSIZE_2 +#define SDIO_DATABLOCK_SIZE_32B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_2) +#define SDIO_DATABLOCK_SIZE_64B (SDIO_DCTRL_DBLOCKSIZE_1|SDIO_DCTRL_DBLOCKSIZE_2) +#define SDIO_DATABLOCK_SIZE_128B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_1|SDIO_DCTRL_DBLOCKSIZE_2) +#define SDIO_DATABLOCK_SIZE_256B SDIO_DCTRL_DBLOCKSIZE_3 +#define SDIO_DATABLOCK_SIZE_512B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_3) +#define SDIO_DATABLOCK_SIZE_1024B (SDIO_DCTRL_DBLOCKSIZE_1|SDIO_DCTRL_DBLOCKSIZE_3) +#define SDIO_DATABLOCK_SIZE_2048B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_1|SDIO_DCTRL_DBLOCKSIZE_3) +#define SDIO_DATABLOCK_SIZE_4096B (SDIO_DCTRL_DBLOCKSIZE_2|SDIO_DCTRL_DBLOCKSIZE_3) +#define SDIO_DATABLOCK_SIZE_8192B (SDIO_DCTRL_DBLOCKSIZE_0|SDIO_DCTRL_DBLOCKSIZE_2|SDIO_DCTRL_DBLOCKSIZE_3) +#define SDIO_DATABLOCK_SIZE_16384B (SDIO_DCTRL_DBLOCKSIZE_1|SDIO_DCTRL_DBLOCKSIZE_2|SDIO_DCTRL_DBLOCKSIZE_3) + +#define IS_SDIO_BLOCK_SIZE(SIZE) (((SIZE) == SDIO_DATABLOCK_SIZE_1B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_2B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_4B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_8B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_16B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_32B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_64B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_128B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_256B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_512B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_1024B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_2048B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_4096B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_8192B) || \ + ((SIZE) == SDIO_DATABLOCK_SIZE_16384B)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Transfer_Direction Transfer Direction + * @{ + */ +#define SDIO_TRANSFER_DIR_TO_CARD 0x00000000U +#define SDIO_TRANSFER_DIR_TO_SDIO SDIO_DCTRL_DTDIR + +#define IS_SDIO_TRANSFER_DIR(DIR) (((DIR) == SDIO_TRANSFER_DIR_TO_CARD) || \ + ((DIR) == SDIO_TRANSFER_DIR_TO_SDIO)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Transfer_Type Transfer Type + * @{ + */ +#define SDIO_TRANSFER_MODE_BLOCK 0x00000000U +#define SDIO_TRANSFER_MODE_STREAM SDIO_DCTRL_DTMODE + +#define IS_SDIO_TRANSFER_MODE(MODE) (((MODE) == SDIO_TRANSFER_MODE_BLOCK) || \ + ((MODE) == SDIO_TRANSFER_MODE_STREAM)) +/** + * @} + */ + +/** @defgroup SDIO_LL_DPSM_State DPSM State + * @{ + */ +#define SDIO_DPSM_DISABLE 0x00000000U +#define SDIO_DPSM_ENABLE SDIO_DCTRL_DTEN + +#define IS_SDIO_DPSM(DPSM) (((DPSM) == SDIO_DPSM_DISABLE) ||\ + ((DPSM) == SDIO_DPSM_ENABLE)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Read_Wait_Mode Read Wait Mode + * @{ + */ +#define SDIO_READ_WAIT_MODE_DATA2 0x00000000U +#define SDIO_READ_WAIT_MODE_CLK (SDIO_DCTRL_RWMOD) + +#define IS_SDIO_READWAIT_MODE(MODE) (((MODE) == SDIO_READ_WAIT_MODE_CLK) || \ + ((MODE) == SDIO_READ_WAIT_MODE_DATA2)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Interrupt_sources Interrupt Sources + * @{ + */ +#define SDIO_IT_CCRCFAIL SDIO_MASK_CCRCFAILIE +#define SDIO_IT_DCRCFAIL SDIO_MASK_DCRCFAILIE +#define SDIO_IT_CTIMEOUT SDIO_MASK_CTIMEOUTIE +#define SDIO_IT_DTIMEOUT SDIO_MASK_DTIMEOUTIE +#define SDIO_IT_TXUNDERR SDIO_MASK_TXUNDERRIE +#define SDIO_IT_RXOVERR SDIO_MASK_RXOVERRIE +#define SDIO_IT_CMDREND SDIO_MASK_CMDRENDIE +#define SDIO_IT_CMDSENT SDIO_MASK_CMDSENTIE +#define SDIO_IT_DATAEND SDIO_MASK_DATAENDIE +#if defined(SDIO_STA_STBITERR) +#define SDIO_IT_STBITERR SDIO_MASK_STBITERRIE +#endif +#define SDIO_IT_DBCKEND SDIO_MASK_DBCKENDIE +#define SDIO_IT_CMDACT SDIO_MASK_CMDACTIE +#define SDIO_IT_TXACT SDIO_MASK_TXACTIE +#define SDIO_IT_RXACT SDIO_MASK_RXACTIE +#define SDIO_IT_TXFIFOHE SDIO_MASK_TXFIFOHEIE +#define SDIO_IT_RXFIFOHF SDIO_MASK_RXFIFOHFIE +#define SDIO_IT_TXFIFOF SDIO_MASK_TXFIFOFIE +#define SDIO_IT_RXFIFOF SDIO_MASK_RXFIFOFIE +#define SDIO_IT_TXFIFOE SDIO_MASK_TXFIFOEIE +#define SDIO_IT_RXFIFOE SDIO_MASK_RXFIFOEIE +#define SDIO_IT_TXDAVL SDIO_MASK_TXDAVLIE +#define SDIO_IT_RXDAVL SDIO_MASK_RXDAVLIE +#define SDIO_IT_SDIOIT SDIO_MASK_SDIOITIE +#if defined(SDIO_CMD_CEATACMD) +#define SDIO_IT_CEATAEND SDIO_MASK_CEATAENDIE +#endif +/** + * @} + */ + +/** @defgroup SDIO_LL_Flags Flags + * @{ + */ +#define SDIO_FLAG_CCRCFAIL SDIO_STA_CCRCFAIL +#define SDIO_FLAG_DCRCFAIL SDIO_STA_DCRCFAIL +#define SDIO_FLAG_CTIMEOUT SDIO_STA_CTIMEOUT +#define SDIO_FLAG_DTIMEOUT SDIO_STA_DTIMEOUT +#define SDIO_FLAG_TXUNDERR SDIO_STA_TXUNDERR +#define SDIO_FLAG_RXOVERR SDIO_STA_RXOVERR +#define SDIO_FLAG_CMDREND SDIO_STA_CMDREND +#define SDIO_FLAG_CMDSENT SDIO_STA_CMDSENT +#define SDIO_FLAG_DATAEND SDIO_STA_DATAEND +#if defined(SDIO_STA_STBITERR) +#define SDIO_FLAG_STBITERR SDIO_STA_STBITERR +#endif +#define SDIO_FLAG_DBCKEND SDIO_STA_DBCKEND +#define SDIO_FLAG_CMDACT SDIO_STA_CMDACT +#define SDIO_FLAG_TXACT SDIO_STA_TXACT +#define SDIO_FLAG_RXACT SDIO_STA_RXACT +#define SDIO_FLAG_TXFIFOHE SDIO_STA_TXFIFOHE +#define SDIO_FLAG_RXFIFOHF SDIO_STA_RXFIFOHF +#define SDIO_FLAG_TXFIFOF SDIO_STA_TXFIFOF +#define SDIO_FLAG_RXFIFOF SDIO_STA_RXFIFOF +#define SDIO_FLAG_TXFIFOE SDIO_STA_TXFIFOE +#define SDIO_FLAG_RXFIFOE SDIO_STA_RXFIFOE +#define SDIO_FLAG_TXDAVL SDIO_STA_TXDAVL +#define SDIO_FLAG_RXDAVL SDIO_STA_RXDAVL +#define SDIO_FLAG_SDIOIT SDIO_STA_SDIOIT +#if defined(SDIO_CMD_CEATACMD) +#define SDIO_FLAG_CEATAEND SDIO_STA_CEATAEND +#endif +#define SDIO_STATIC_FLAGS ((uint32_t)(SDIO_FLAG_CCRCFAIL | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_CTIMEOUT |\ + SDIO_FLAG_DTIMEOUT | SDIO_FLAG_TXUNDERR | SDIO_FLAG_RXOVERR |\ + SDIO_FLAG_CMDREND | SDIO_FLAG_CMDSENT | SDIO_FLAG_DATAEND |\ + SDIO_FLAG_DBCKEND | SDIO_FLAG_SDIOIT)) + +#define SDIO_STATIC_CMD_FLAGS ((uint32_t)(SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CTIMEOUT | SDIO_FLAG_CMDREND |\ + SDIO_FLAG_CMDSENT)) + +#define SDIO_STATIC_DATA_FLAGS ((uint32_t)(SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_TXUNDERR |\ + SDIO_FLAG_RXOVERR | SDIO_FLAG_DATAEND | SDIO_FLAG_DBCKEND)) +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SDIO_LL_Exported_macros SDIO_LL Exported Macros + * @{ + */ + +/** @defgroup SDMMC_LL_Alias_Region Bit Address in the alias region + * @{ + */ +/* ------------ SDIO registers bit address in the alias region -------------- */ +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* --- CLKCR Register ---*/ +/* Alias word address of CLKEN bit */ +#define CLKCR_OFFSET (SDIO_OFFSET + 0x04U) +#define CLKEN_BITNUMBER 0x08U +#define CLKCR_CLKEN_BB (PERIPH_BB_BASE + (CLKCR_OFFSET * 32U) + (CLKEN_BITNUMBER * 4U)) + +/* --- CMD Register ---*/ +/* Alias word address of SDIOSUSPEND bit */ +#define CMD_OFFSET (SDIO_OFFSET + 0x0CU) +#define SDIOSUSPEND_BITNUMBER 0x0BU +#define CMD_SDIOSUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32U) + (SDIOSUSPEND_BITNUMBER * 4U)) + +/* Alias word address of ENCMDCOMPL bit */ +#define ENCMDCOMPL_BITNUMBER 0x0CU +#define CMD_ENCMDCOMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32U) + (ENCMDCOMPL_BITNUMBER * 4U)) + +/* Alias word address of NIEN bit */ +#define NIEN_BITNUMBER 0x0DU +#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32U) + (NIEN_BITNUMBER * 4U)) + +/* Alias word address of ATACMD bit */ +#define ATACMD_BITNUMBER 0x0EU +#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32U) + (ATACMD_BITNUMBER * 4U)) + +/* --- DCTRL Register ---*/ +/* Alias word address of DMAEN bit */ +#define DCTRL_OFFSET (SDIO_OFFSET + 0x2CU) +#define DMAEN_BITNUMBER 0x03U +#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32U) + (DMAEN_BITNUMBER * 4U)) + +/* Alias word address of RWSTART bit */ +#define RWSTART_BITNUMBER 0x08U +#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32U) + (RWSTART_BITNUMBER * 4U)) + +/* Alias word address of RWSTOP bit */ +#define RWSTOP_BITNUMBER 0x09U +#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32U) + (RWSTOP_BITNUMBER * 4U)) + +/* Alias word address of RWMOD bit */ +#define RWMOD_BITNUMBER 0x0AU +#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32U) + (RWMOD_BITNUMBER * 4U)) + +/* Alias word address of SDIOEN bit */ +#define SDIOEN_BITNUMBER 0x0BU +#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32U) + (SDIOEN_BITNUMBER * 4U)) +/** + * @} + */ + +/** @defgroup SDIO_LL_Register Bits And Addresses Definitions + * @brief SDIO_LL registers bit address in the alias region + * @{ + */ +/* ---------------------- SDIO registers bit mask --------------------------- */ +/* --- CLKCR Register ---*/ +/* CLKCR register clear mask */ +#define CLKCR_CLEAR_MASK ((uint32_t)(SDIO_CLKCR_CLKDIV | SDIO_CLKCR_PWRSAV |\ + SDIO_CLKCR_BYPASS | SDIO_CLKCR_WIDBUS |\ + SDIO_CLKCR_NEGEDGE | SDIO_CLKCR_HWFC_EN)) + +/* --- DCTRL Register ---*/ +/* SDIO DCTRL Clear Mask */ +#define DCTRL_CLEAR_MASK ((uint32_t)(SDIO_DCTRL_DTEN | SDIO_DCTRL_DTDIR |\ + SDIO_DCTRL_DTMODE | SDIO_DCTRL_DBLOCKSIZE)) + +/* --- CMD Register ---*/ +/* CMD Register clear mask */ +#define CMD_CLEAR_MASK ((uint32_t)(SDIO_CMD_CMDINDEX | SDIO_CMD_WAITRESP |\ + SDIO_CMD_WAITINT | SDIO_CMD_WAITPEND |\ + SDIO_CMD_CPSMEN | SDIO_CMD_SDIOSUSPEND)) + +/* SDIO Initialization Frequency (400KHz max) */ +#define SDIO_INIT_CLK_DIV ((uint8_t)0x76) /* 48MHz / (SDMMC_INIT_CLK_DIV + 2) < 400KHz */ + +/* SDIO Data Transfer Frequency (25MHz max) */ +#define SDIO_TRANSFER_CLK_DIV ((uint8_t)0x0) /* 48MHz / (SDMMC_TRANSFER_CLK_DIV + 2) < 25MHz */ +/** + * @} + */ + +/** @defgroup SDIO_LL_Interrupt_Clock Interrupt And Clock Configuration + * @brief macros to handle interrupts and specific clock configurations + * @{ + */ + +/** + * @brief Enable the SDIO device. + * @param __INSTANCE__: SDIO Instance + * @retval None + */ +#define __SDIO_ENABLE(__INSTANCE__) (*(__IO uint32_t *)CLKCR_CLKEN_BB = ENABLE) + +/** + * @brief Disable the SDIO device. + * @param __INSTANCE__: SDIO Instance + * @retval None + */ +#define __SDIO_DISABLE(__INSTANCE__) (*(__IO uint32_t *)CLKCR_CLKEN_BB = DISABLE) + +/** + * @brief Enable the SDIO DMA transfer. + * @param __INSTANCE__: SDIO Instance + * @retval None + */ +#define __SDIO_DMA_ENABLE(__INSTANCE__) (*(__IO uint32_t *)DCTRL_DMAEN_BB = ENABLE) + +/** + * @brief Disable the SDIO DMA transfer. + * @param __INSTANCE__: SDIO Instance + * @retval None + */ +#define __SDIO_DMA_DISABLE(__INSTANCE__) (*(__IO uint32_t *)DCTRL_DMAEN_BB = DISABLE) + +/** + * @brief Enable the SDIO device interrupt. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __INTERRUPT__ : specifies the SDIO interrupt sources to be enabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __SDIO_ENABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->MASK |= (__INTERRUPT__)) + +/** + * @brief Disable the SDIO device interrupt. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __INTERRUPT__ : specifies the SDIO interrupt sources to be disabled. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __SDIO_DISABLE_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->MASK &= ~(__INTERRUPT__)) + +/** + * @brief Checks whether the specified SDIO flag is set or not. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __FLAG__: specifies the flag to check. + * This parameter can be one of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_CMDACT: Command transfer in progress + * @arg SDIO_FLAG_TXACT: Data transmit in progress + * @arg SDIO_FLAG_RXACT: Data receive in progress + * @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty + * @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full + * @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full + * @arg SDIO_FLAG_RXFIFOF: Receive FIFO full + * @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty + * @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty + * @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO + * @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO + * @arg SDIO_FLAG_SDIOIT: SDIO interrupt received + * @retval The new state of SDIO_FLAG (SET or RESET). + */ +#define __SDIO_GET_FLAG(__INSTANCE__, __FLAG__) (((__INSTANCE__)->STA &(__FLAG__)) != 0U) + + +/** + * @brief Clears the SDIO pending flags. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __FLAG__: specifies the flag to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) + * @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) + * @arg SDIO_FLAG_CTIMEOUT: Command response timeout + * @arg SDIO_FLAG_DTIMEOUT: Data timeout + * @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error + * @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error + * @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed) + * @arg SDIO_FLAG_CMDSENT: Command sent (no response required) + * @arg SDIO_FLAG_DATAEND: Data end (data counter, DATACOUNT, is zero) + * @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) + * @arg SDIO_FLAG_SDIOIT: SDIO interrupt received + * @retval None + */ +#define __SDIO_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->ICR = (__FLAG__)) + +/** + * @brief Checks whether the specified SDIO interrupt has occurred or not. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __INTERRUPT__: specifies the SDIO interrupt source to check. + * This parameter can be one of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt + * @arg SDIO_IT_CMDACT: Command transfer in progress interrupt + * @arg SDIO_IT_TXACT: Data transmit in progress interrupt + * @arg SDIO_IT_RXACT: Data receive in progress interrupt + * @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt + * @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt + * @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt + * @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt + * @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt + * @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt + * @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt + * @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval The new state of SDIO_IT (SET or RESET). + */ +#define __SDIO_GET_IT (__INSTANCE__, __INTERRUPT__) (((__INSTANCE__)->STA &(__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the SDIO's interrupt pending bits. + * @param __INSTANCE__ : Pointer to SDIO register base + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. + * This parameter can be one or a combination of the following values: + * @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt + * @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt + * @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt + * @arg SDIO_IT_DTIMEOUT: Data timeout interrupt + * @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt + * @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt + * @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt + * @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt + * @arg SDIO_IT_DATAEND: Data end (data counter, DATACOUNT, is zero) interrupt + * @arg SDIO_IT_SDIOIT: SDIO interrupt received interrupt + * @retval None + */ +#define __SDIO_CLEAR_IT(__INSTANCE__, __INTERRUPT__) ((__INSTANCE__)->ICR = (__INTERRUPT__)) + +/** + * @brief Enable Start the SD I/O Read Wait operation. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_START_READWAIT_ENABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_RWSTART_BB = ENABLE) + +/** + * @brief Disable Start the SD I/O Read Wait operations. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_START_READWAIT_DISABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_RWSTART_BB = DISABLE) + +/** + * @brief Enable Start the SD I/O Read Wait operation. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_STOP_READWAIT_ENABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_RWSTOP_BB = ENABLE) + +/** + * @brief Disable Stop the SD I/O Read Wait operations. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_STOP_READWAIT_DISABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_RWSTOP_BB = DISABLE) + +/** + * @brief Enable the SD I/O Mode Operation. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_OPERATION_ENABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_SDIOEN_BB = ENABLE) + +/** + * @brief Disable the SD I/O Mode Operation. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_OPERATION_DISABLE(__INSTANCE__) (*(__IO uint32_t *) DCTRL_SDIOEN_BB = DISABLE) + +/** + * @brief Enable the SD I/O Suspend command sending. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_SUSPEND_CMD_ENABLE(__INSTANCE__) (*(__IO uint32_t *) CMD_SDIOSUSPEND_BB = ENABLE) + +/** + * @brief Disable the SD I/O Suspend command sending. + * @param __INSTANCE__ : Pointer to SDIO register base + * @retval None + */ +#define __SDIO_SUSPEND_CMD_DISABLE(__INSTANCE__) (*(__IO uint32_t *) CMD_SDIOSUSPEND_BB = DISABLE) + +#if defined(SDIO_CMD_CEATACMD) +/** + * @brief Enable the command completion signal. + * @retval None + */ +#define __SDIO_CEATA_CMD_COMPLETION_ENABLE() (*(__IO uint32_t *) CMD_ENCMDCOMPL_BB = ENABLE) + +/** + * @brief Disable the command completion signal. + * @retval None + */ +#define __SDIO_CEATA_CMD_COMPLETION_DISABLE() (*(__IO uint32_t *) CMD_ENCMDCOMPL_BB = DISABLE) + +/** + * @brief Enable the CE-ATA interrupt. + * @retval None + */ +#define __SDIO_CEATA_ENABLE_IT() (*(__IO uint32_t *) CMD_NIEN_BB = (uint32_t)0U) + +/** + * @brief Disable the CE-ATA interrupt. + * @retval None + */ +#define __SDIO_CEATA_DISABLE_IT() (*(__IO uint32_t *) CMD_NIEN_BB = (uint32_t)1U) + +/** + * @brief Enable send CE-ATA command (CMD61). + * @retval None + */ +#define __SDIO_CEATA_SENDCMD_ENABLE() (*(__IO uint32_t *) CMD_ATACMD_BB = ENABLE) + +/** + * @brief Disable send CE-ATA command (CMD61). + * @retval None + */ +#define __SDIO_CEATA_SENDCMD_DISABLE() (*(__IO uint32_t *) CMD_ATACMD_BB = DISABLE) + +#endif +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SDMMC_LL_Exported_Functions + * @{ + */ + +/* Initialization/de-initialization functions **********************************/ +/** @addtogroup HAL_SDMMC_LL_Group1 + * @{ + */ +HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init); +/** + * @} + */ + +/* I/O operation functions *****************************************************/ +/** @addtogroup HAL_SDMMC_LL_Group2 + * @{ + */ +uint32_t SDIO_ReadFIFO(SDIO_TypeDef *SDIOx); +HAL_StatusTypeDef SDIO_WriteFIFO(SDIO_TypeDef *SDIOx, uint32_t *pWriteData); +/** + * @} + */ + +/* Peripheral Control functions ************************************************/ +/** @addtogroup HAL_SDMMC_LL_Group3 + * @{ + */ +HAL_StatusTypeDef SDIO_PowerState_ON(SDIO_TypeDef *SDIOx); +HAL_StatusTypeDef SDIO_PowerState_OFF(SDIO_TypeDef *SDIOx); +uint32_t SDIO_GetPowerState(SDIO_TypeDef *SDIOx); + +/* Command path state machine (CPSM) management functions */ +HAL_StatusTypeDef SDIO_SendCommand(SDIO_TypeDef *SDIOx, SDIO_CmdInitTypeDef *Command); +uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx); +uint32_t SDIO_GetResponse(SDIO_TypeDef *SDIOx, uint32_t Response); + +/* Data path state machine (DPSM) management functions */ +HAL_StatusTypeDef SDIO_ConfigData(SDIO_TypeDef *SDIOx, SDIO_DataInitTypeDef* Data); +uint32_t SDIO_GetDataCounter(SDIO_TypeDef *SDIOx); +uint32_t SDIO_GetFIFOCount(SDIO_TypeDef *SDIOx); + +/* SDMMC Cards mode management functions */ +HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode); +/** + * @} + */ + +/* SDMMC Commands management functions */ +/** @addtogroup HAL_SDMMC_LL_Group4 + * @{ + */ +uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize); +uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); +uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd); +uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd); +uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd); +uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd); +uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd); +uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd); +uint32_t SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd); +uint32_t SDMMC_CmdErase(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdStopTransfer(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdSelDesel(SDIO_TypeDef *SDIOx, uint64_t Addr); +uint32_t SDMMC_CmdGoIdleState(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdOperCond(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdAppCommand(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdAppOperCommand(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdBusWidth(SDIO_TypeDef *SDIOx, uint32_t BusWidth); +uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA); +uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA); +uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument); +uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument); +/** + * @} + */ + +/* SDMMC Responses management functions *****************************************/ +/** @addtogroup HAL_SDMMC_LL_Group5 + * @{ + */ +uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout); +uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx); +uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA); +uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* SDIO */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_SDMMC_H */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h new file mode 100644 index 0000000..4f3b030 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_spi.h @@ -0,0 +1,2027 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_spi.h + * @author MCD Application Team + * @brief Header file of SPI 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 STM32F4xx_LL_SPI_H +#define STM32F4xx_LL_SPI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4) || defined (SPI5) || defined(SPI6) + +/** @defgroup SPI_LL SPI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_ES_INIT SPI Exported Init structure + * @{ + */ + +/** + * @brief SPI Init structures definition + */ +typedef struct +{ + uint32_t TransferDirection; /*!< Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_LL_EC_TRANSFER_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferDirection().*/ + + uint32_t Mode; /*!< Specifies the SPI mode (Master/Slave). + This parameter can be a value of @ref SPI_LL_EC_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetMode().*/ + + uint32_t DataWidth; /*!< Specifies the SPI data width. + This parameter can be a value of @ref SPI_LL_EC_DATAWIDTH. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetDataWidth().*/ + + uint32_t ClockPolarity; /*!< Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_LL_EC_POLARITY. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPolarity().*/ + + uint32_t ClockPhase; /*!< Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_LL_EC_PHASE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetClockPhase().*/ + + uint32_t NSS; /*!< Specifies whether the NSS signal is managed by hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_LL_EC_NSS_MODE. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetNSSMode().*/ + + uint32_t BaudRate; /*!< Specifies the BaudRate prescaler value which will be used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_LL_EC_BAUDRATEPRESCALER. + @note The communication clock is derived from the master clock. The slave clock does not need to be set. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetBaudRatePrescaler().*/ + + uint32_t BitOrder; /*!< Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_LL_EC_BIT_ORDER. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetTransferBitOrder().*/ + + uint32_t CRCCalculation; /*!< Specifies if the CRC calculation is enabled or not. + This parameter can be a value of @ref SPI_LL_EC_CRC_CALCULATION. + + This feature can be modified afterwards using unitary functions @ref LL_SPI_EnableCRC() and @ref LL_SPI_DisableCRC().*/ + + uint32_t CRCPoly; /*!< Specifies the polynomial used for the CRC calculation. + This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF. + + This feature can be modified afterwards using unitary function @ref LL_SPI_SetCRCPolynomial().*/ + +} LL_SPI_InitTypeDef; + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Constants SPI Exported Constants + * @{ + */ + +/** @defgroup SPI_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_SPI_ReadReg function + * @{ + */ +#define LL_SPI_SR_RXNE SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_SPI_SR_TXE SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_SPI_SR_BSY SPI_SR_BSY /*!< Busy flag */ +#define LL_SPI_SR_CRCERR SPI_SR_CRCERR /*!< CRC error flag */ +#define LL_SPI_SR_MODF SPI_SR_MODF /*!< Mode fault flag */ +#define LL_SPI_SR_OVR SPI_SR_OVR /*!< Overrun flag */ +#define LL_SPI_SR_FRE SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_SPI_CR2_RXNEIE SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_SPI_CR2_TXEIE SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_SPI_CR2_ERRIE SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_SPI_MODE_MASTER (SPI_CR1_MSTR | SPI_CR1_SSI) /*!< Master configuration */ +#define LL_SPI_MODE_SLAVE 0x00000000U /*!< Slave configuration */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PROTOCOL Serial Protocol + * @{ + */ +#define LL_SPI_PROTOCOL_MOTOROLA 0x00000000U /*!< Motorola mode. Used as default value */ +#define LL_SPI_PROTOCOL_TI (SPI_CR2_FRF) /*!< TI mode */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_SPI_PHASE_1EDGE 0x00000000U /*!< First clock transition is the first data capture edge */ +#define LL_SPI_PHASE_2EDGE (SPI_CR1_CPHA) /*!< Second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_SPI_POLARITY_LOW 0x00000000U /*!< Clock to 0 when idle */ +#define LL_SPI_POLARITY_HIGH (SPI_CR1_CPOL) /*!< Clock to 1 when idle */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BAUDRATEPRESCALER Baud Rate Prescaler + * @{ + */ +#define LL_SPI_BAUDRATEPRESCALER_DIV2 0x00000000U /*!< BaudRate control equal to fPCLK/2 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV4 (SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/4 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV8 (SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/8 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/16 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV32 (SPI_CR1_BR_2) /*!< BaudRate control equal to fPCLK/32 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/64 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV128 (SPI_CR1_BR_2 | SPI_CR1_BR_1) /*!< BaudRate control equal to fPCLK/128 */ +#define LL_SPI_BAUDRATEPRESCALER_DIV256 (SPI_CR1_BR_2 | SPI_CR1_BR_1 | SPI_CR1_BR_0) /*!< BaudRate control equal to fPCLK/256 */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_BIT_ORDER Transmission Bit Order + * @{ + */ +#define LL_SPI_LSB_FIRST (SPI_CR1_LSBFIRST) /*!< Data is transmitted/received with the LSB first */ +#define LL_SPI_MSB_FIRST 0x00000000U /*!< Data is transmitted/received with the MSB first */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_TRANSFER_MODE Transfer Mode + * @{ + */ +#define LL_SPI_FULL_DUPLEX 0x00000000U /*!< Full-Duplex mode. Rx and Tx transfer on 2 lines */ +#define LL_SPI_SIMPLEX_RX (SPI_CR1_RXONLY) /*!< Simplex Rx mode. Rx transfer only on 1 line */ +#define LL_SPI_HALF_DUPLEX_RX (SPI_CR1_BIDIMODE) /*!< Half-Duplex Rx mode. Rx transfer on 1 line */ +#define LL_SPI_HALF_DUPLEX_TX (SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE) /*!< Half-Duplex Tx mode. Tx transfer on 1 line */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_NSS_MODE Slave Select Pin Mode + * @{ + */ +#define LL_SPI_NSS_SOFT (SPI_CR1_SSM) /*!< NSS managed internally. NSS pin not used and free */ +#define LL_SPI_NSS_HARD_INPUT 0x00000000U /*!< NSS pin used in Input. Only used in Master mode */ +#define LL_SPI_NSS_HARD_OUTPUT (((uint32_t)SPI_CR2_SSOE << 16U)) /*!< NSS pin used in Output. Only used in Slave mode as chip select */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_DATAWIDTH Datawidth + * @{ + */ +#define LL_SPI_DATAWIDTH_8BIT 0x00000000U /*!< Data length for SPI transfer: 8 bits */ +#define LL_SPI_DATAWIDTH_16BIT (SPI_CR1_DFF) /*!< Data length for SPI transfer: 16 bits */ +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup SPI_LL_EC_CRC_CALCULATION CRC Calculation + * @{ + */ +#define LL_SPI_CRCCALCULATION_DISABLE 0x00000000U /*!< CRC calculation disabled */ +#define LL_SPI_CRCCALCULATION_ENABLE (SPI_CR1_CRCEN) /*!< CRC calculation enabled */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Macros SPI Exported Macros + * @{ + */ + +/** @defgroup SPI_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_SPI_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in SPI register + * @param __INSTANCE__ SPI Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_SPI_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_LL_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Enable SPI peripheral + * @rmtoll CR1 SPE LL_SPI_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Disable SPI peripheral + * @note When disabling the SPI, follow the procedure described in the Reference Manual. + * @rmtoll CR1 SPE LL_SPI_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Check if SPI peripheral is enabled + * @rmtoll CR1 SPE LL_SPI_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabled(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_SPE) == (SPI_CR1_SPE)) ? 1UL : 0UL); +} + +/** + * @brief Set SPI operation mode to Master or Slave + * @note This bit should not be changed when communication is ongoing. + * @rmtoll CR1 MSTR LL_SPI_SetMode\n + * CR1 SSI LL_SPI_SetMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI, Mode); +} + +/** + * @brief Get SPI operation mode (Master or Slave) + * @rmtoll CR1 MSTR LL_SPI_GetMode\n + * CR1 SSI LL_SPI_GetMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_MODE_MASTER + * @arg @ref LL_SPI_MODE_SLAVE + */ +__STATIC_INLINE uint32_t LL_SPI_GetMode(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_MSTR | SPI_CR1_SSI)); +} + +/** + * @brief Set serial protocol used + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR2 FRF LL_SPI_SetStandard + * @param SPIx SPI Instance + * @param Standard This parameter can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) +{ + MODIFY_REG(SPIx->CR2, SPI_CR2_FRF, Standard); +} + +/** + * @brief Get serial protocol used + * @rmtoll CR2 FRF LL_SPI_GetStandard + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PROTOCOL_MOTOROLA + * @arg @ref LL_SPI_PROTOCOL_TI + */ +__STATIC_INLINE uint32_t LL_SPI_GetStandard(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR2, SPI_CR2_FRF)); +} + +/** + * @brief Set clock phase + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPHA LL_SPI_SetClockPhase + * @param SPIx SPI Instance + * @param ClockPhase This parameter can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPhase(SPI_TypeDef *SPIx, uint32_t ClockPhase) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPHA, ClockPhase); +} + +/** + * @brief Get clock phase + * @rmtoll CR1 CPHA LL_SPI_GetClockPhase + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_PHASE_1EDGE + * @arg @ref LL_SPI_PHASE_2EDGE + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPhase(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPHA)); +} + +/** + * @brief Set clock polarity + * @note This bit should not be changed when communication is ongoing. + * This bit is not used in SPI TI mode. + * @rmtoll CR1 CPOL LL_SPI_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_CPOL, ClockPolarity); +} + +/** + * @brief Get clock polarity + * @rmtoll CR1 CPOL LL_SPI_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_POLARITY_LOW + * @arg @ref LL_SPI_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_SPI_GetClockPolarity(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_CPOL)); +} + +/** + * @brief Set baud rate prescaler + * @note These bits should not be changed when communication is ongoing. SPI BaudRate = fPCLK/Prescaler. + * @rmtoll CR1 BR LL_SPI_SetBaudRatePrescaler + * @param SPIx SPI Instance + * @param BaudRate This parameter can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetBaudRatePrescaler(SPI_TypeDef *SPIx, uint32_t BaudRate) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_BR, BaudRate); +} + +/** + * @brief Get baud rate prescaler + * @rmtoll CR1 BR LL_SPI_GetBaudRatePrescaler + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV2 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV4 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV8 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV16 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV32 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV64 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV128 + * @arg @ref LL_SPI_BAUDRATEPRESCALER_DIV256 + */ +__STATIC_INLINE uint32_t LL_SPI_GetBaudRatePrescaler(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_BR)); +} + +/** + * @brief Set transfer bit order + * @note This bit should not be changed when communication is ongoing. This bit is not used in SPI TI mode. + * @rmtoll CR1 LSBFIRST LL_SPI_SetTransferBitOrder + * @param SPIx SPI Instance + * @param BitOrder This parameter can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferBitOrder(SPI_TypeDef *SPIx, uint32_t BitOrder) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_LSBFIRST, BitOrder); +} + +/** + * @brief Get transfer bit order + * @rmtoll CR1 LSBFIRST LL_SPI_GetTransferBitOrder + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_LSB_FIRST + * @arg @ref LL_SPI_MSB_FIRST + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferBitOrder(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_LSBFIRST)); +} + +/** + * @brief Set transfer direction mode + * @note For Half-Duplex mode, Rx Direction is set by default. + * In master mode, the MOSI pin is used and in slave mode, the MISO pin is used for Half-Duplex. + * @rmtoll CR1 RXONLY LL_SPI_SetTransferDirection\n + * CR1 BIDIMODE LL_SPI_SetTransferDirection\n + * CR1 BIDIOE LL_SPI_SetTransferDirection + * @param SPIx SPI Instance + * @param TransferDirection This parameter can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetTransferDirection(SPI_TypeDef *SPIx, uint32_t TransferDirection) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE, TransferDirection); +} + +/** + * @brief Get transfer direction mode + * @rmtoll CR1 RXONLY LL_SPI_GetTransferDirection\n + * CR1 BIDIMODE LL_SPI_GetTransferDirection\n + * CR1 BIDIOE LL_SPI_GetTransferDirection + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_FULL_DUPLEX + * @arg @ref LL_SPI_SIMPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_RX + * @arg @ref LL_SPI_HALF_DUPLEX_TX + */ +__STATIC_INLINE uint32_t LL_SPI_GetTransferDirection(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_RXONLY | SPI_CR1_BIDIMODE | SPI_CR1_BIDIOE)); +} + +/** + * @brief Set frame data width + * @rmtoll CR1 DFF LL_SPI_SetDataWidth + * @param SPIx SPI Instance + * @param DataWidth This parameter can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetDataWidth(SPI_TypeDef *SPIx, uint32_t DataWidth) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_DFF, DataWidth); +} + +/** + * @brief Get frame data width + * @rmtoll CR1 DFF LL_SPI_GetDataWidth + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_DATAWIDTH_8BIT + * @arg @ref LL_SPI_DATAWIDTH_16BIT + */ +__STATIC_INLINE uint32_t LL_SPI_GetDataWidth(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->CR1, SPI_CR1_DFF)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_CRC_Management CRC Management + * @{ + */ + +/** + * @brief Enable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_EnableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableCRC(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Disable CRC + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_DisableCRC + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableCRC(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR1, SPI_CR1_CRCEN); +} + +/** + * @brief Check if CRC is enabled + * @note This bit should be written only when SPI is disabled (SPE = 0) for correct operation. + * @rmtoll CR1 CRCEN LL_SPI_IsEnabledCRC + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledCRC(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR1, SPI_CR1_CRCEN) == (SPI_CR1_CRCEN)) ? 1UL : 0UL); +} + +/** + * @brief Set CRCNext to transfer CRC on the line + * @note This bit has to be written as soon as the last data is written in the SPIx_DR register. + * @rmtoll CR1 CRCNEXT LL_SPI_SetCRCNext + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCNext(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR1, SPI_CR1_CRCNEXT); +} + +/** + * @brief Set polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_SetCRCPolynomial + * @param SPIx SPI Instance + * @param CRCPoly This parameter must be a number between Min_Data = 0x00 and Max_Data = 0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetCRCPolynomial(SPI_TypeDef *SPIx, uint32_t CRCPoly) +{ + WRITE_REG(SPIx->CRCPR, (uint16_t)CRCPoly); +} + +/** + * @brief Get polynomial for CRC calculation + * @rmtoll CRCPR CRCPOLY LL_SPI_GetCRCPolynomial + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetCRCPolynomial(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->CRCPR)); +} + +/** + * @brief Get Rx CRC + * @rmtoll RXCRCR RXCRC LL_SPI_GetRxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetRxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->RXCRCR)); +} + +/** + * @brief Get Tx CRC + * @rmtoll TXCRCR TXCRC LL_SPI_GetTxCRC + * @param SPIx SPI Instance + * @retval Returned value is a number between Min_Data = 0x00 and Max_Data = 0xFFFF + */ +__STATIC_INLINE uint32_t LL_SPI_GetTxCRC(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_REG(SPIx->TXCRCR)); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_NSS_Management Slave Select Pin Management + * @{ + */ + +/** + * @brief Set NSS mode + * @note LL_SPI_NSS_SOFT Mode is not used in SPI TI mode. + * @rmtoll CR1 SSM LL_SPI_SetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_SetNSSMode + * @param SPIx SPI Instance + * @param NSS This parameter can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + * @retval None + */ +__STATIC_INLINE void LL_SPI_SetNSSMode(SPI_TypeDef *SPIx, uint32_t NSS) +{ + MODIFY_REG(SPIx->CR1, SPI_CR1_SSM, NSS); + MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, ((uint32_t)(NSS >> 16U))); +} + +/** + * @brief Get NSS mode + * @rmtoll CR1 SSM LL_SPI_GetNSSMode\n + * @rmtoll CR2 SSOE LL_SPI_GetNSSMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_SPI_NSS_SOFT + * @arg @ref LL_SPI_NSS_HARD_INPUT + * @arg @ref LL_SPI_NSS_HARD_OUTPUT + */ +__STATIC_INLINE uint32_t LL_SPI_GetNSSMode(SPI_TypeDef *SPIx) +{ + uint32_t Ssm = (READ_BIT(SPIx->CR1, SPI_CR1_SSM)); + uint32_t Ssoe = (READ_BIT(SPIx->CR2, SPI_CR2_SSOE) << 16U); + return (Ssm | Ssoe); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_FLAG_Management FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_SPI_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_SPI_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL); +} + +/** + * @brief Get CRC error flag + * @rmtoll SR CRCERR LL_SPI_IsActiveFlag_CRCERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_CRCERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CRCERR) == (SPI_SR_CRCERR)) ? 1UL : 0UL); +} + +/** + * @brief Get mode fault error flag + * @rmtoll SR MODF LL_SPI_IsActiveFlag_MODF + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_MODF(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_MODF) == (SPI_SR_MODF)) ? 1UL : 0UL); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_SPI_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_OVR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_OVR) == (SPI_SR_OVR)) ? 1UL : 0UL); +} + +/** + * @brief Get busy flag + * @note The BSY flag is cleared under any one of the following conditions: + * -When the SPI is correctly disabled + * -When a fault is detected in Master mode (MODF bit set to 1) + * -In Master mode, when it finishes a data transmission and no new data is ready to be + * sent + * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between + * each data transfer. + * @rmtoll SR BSY LL_SPI_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL); +} + +/** + * @brief Get frame format error flag + * @rmtoll SR FRE LL_SPI_IsActiveFlag_FRE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_FRE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_FRE) == (SPI_SR_FRE)) ? 1UL : 0UL); +} + +/** + * @brief Clear CRC error flag + * @rmtoll SR CRCERR LL_SPI_ClearFlag_CRCERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_CRCERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->SR, SPI_SR_CRCERR); +} + +/** + * @brief Clear mode fault error flag + * @note Clearing this flag is done by a read access to the SPIx_SR + * register followed by a write access to the SPIx_CR1 register + * @rmtoll SR MODF LL_SPI_ClearFlag_MODF + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_MODF(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg_sr; + tmpreg_sr = SPIx->SR; + (void) tmpreg_sr; + CLEAR_BIT(SPIx->CR1, SPI_CR1_SPE); +} + +/** + * @brief Clear overrun error flag + * @note Clearing this flag is done by a read access to the SPIx_DR + * register followed by a read access to the SPIx_SR register + * @rmtoll SR OVR LL_SPI_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->DR; + (void) tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @brief Clear frame format error flag + * @note Clearing this flag is done by reading SPIx_SR register + * @rmtoll SR FRE LL_SPI_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void) tmpreg; +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_IT_Management Interrupt Management + * @{ + */ + +/** + * @brief Enable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Enable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Enable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Disable error interrupt + * @note This bit controls the generation of an interrupt when an error condition occurs (CRCERR, OVR, MODF in SPI mode, FRE at TI mode). + * @rmtoll CR2 ERRIE LL_SPI_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_ERRIE); +} + +/** + * @brief Disable Rx buffer not empty interrupt + * @rmtoll CR2 RXNEIE LL_SPI_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXNEIE); +} + +/** + * @brief Disable Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXEIE); +} + +/** + * @brief Check if error interrupt is enabled + * @rmtoll CR2 ERRIE LL_SPI_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_ERR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_ERRIE) == (SPI_CR2_ERRIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Rx buffer not empty interrupt is enabled + * @rmtoll CR2 RXNEIE LL_SPI_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_RXNE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXNEIE) == (SPI_CR2_RXNEIE)) ? 1UL : 0UL); +} + +/** + * @brief Check if Tx buffer empty interrupt + * @rmtoll CR2 TXEIE LL_SPI_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledIT_TXE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXEIE) == (SPI_CR2_TXEIE)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DMA_Management DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_SPI_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_RXDMAEN); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_SPI_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_RX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_RXDMAEN) == (SPI_CR2_RXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_SPI_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_SPI_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->CR2, SPI_CR2_TXDMAEN); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_SPI_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_SPI_IsEnabledDMAReq_TX(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->CR2, SPI_CR2_TXDMAEN) == (SPI_CR2_TXDMAEN)) ? 1UL : 0UL); +} + +/** + * @brief Get the data register address used for DMA transfer + * @rmtoll DR DR LL_SPI_DMA_GetRegAddr + * @param SPIx SPI Instance + * @retval Address of data register + */ +__STATIC_INLINE uint32_t LL_SPI_DMA_GetRegAddr(SPI_TypeDef *SPIx) +{ + return (uint32_t) &(SPIx->DR); +} + +/** + * @} + */ + +/** @defgroup SPI_LL_EF_DATA_Management DATA Management + * @{ + */ + +/** + * @brief Read 8-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData8 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFF + */ +__STATIC_INLINE uint8_t LL_SPI_ReceiveData8(SPI_TypeDef *SPIx) +{ + return (*((__IO uint8_t *)&SPIx->DR)); +} + +/** + * @brief Read 16-Bits in the data register + * @rmtoll DR DR LL_SPI_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx) +{ + return (uint16_t)(READ_REG(SPIx->DR)); +} + +/** + * @brief Write 8-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData8 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData8(SPI_TypeDef *SPIx, uint8_t TxData) +{ +#if defined (__GNUC__) + __IO uint8_t *spidr = ((__IO uint8_t *)&SPIx->DR); + *spidr = TxData; +#else + *((__IO uint8_t *)&SPIx->DR) = TxData; +#endif /* __GNUC__ */ +} + +/** + * @brief Write 16-Bits in the data register + * @rmtoll DR DR LL_SPI_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x00 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ +#if defined (__GNUC__) + __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR); + *spidr = TxData; +#else + SPIx->DR = TxData; +#endif /* __GNUC__ */ +} + +/** + * @} + */ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup SPI_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx); +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct); +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct); + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup I2S_LL I2S + * @{ + */ + +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/* Exported types ------------------------------------------------------------*/ +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2S_LL_ES_INIT I2S Exported Init structure + * @{ + */ + +/** + * @brief I2S Init structure definition + */ + +typedef struct +{ + uint32_t Mode; /*!< Specifies the I2S operating mode. + This parameter can be a value of @ref I2S_LL_EC_MODE + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetTransferMode().*/ + + uint32_t Standard; /*!< Specifies the standard used for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_STANDARD + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetStandard().*/ + + + uint32_t DataFormat; /*!< Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_DATA_FORMAT + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetDataFormat().*/ + + + uint32_t MCLKOutput; /*!< Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_LL_EC_MCLK_OUTPUT + + This feature can be modified afterwards using unitary functions @ref LL_I2S_EnableMasterClock() or @ref LL_I2S_DisableMasterClock.*/ + + + uint32_t AudioFreq; /*!< Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_LL_EC_AUDIO_FREQ + + Audio Frequency can be modified afterwards using Reference manual formulas to calculate Prescaler Linear, Parity + and unitary functions @ref LL_I2S_SetPrescalerLinear() and @ref LL_I2S_SetPrescalerParity() to set it.*/ + + + uint32_t ClockPolarity; /*!< Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_LL_EC_POLARITY + + This feature can be modified afterwards using unitary function @ref LL_I2S_SetClockPolarity().*/ + +} LL_I2S_InitTypeDef; + +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup I2S_LL_Exported_Constants I2S Exported Constants + * @{ + */ + +/** @defgroup I2S_LL_EC_GET_FLAG Get Flags Defines + * @brief Flags defines which can be used with LL_I2S_ReadReg function + * @{ + */ +#define LL_I2S_SR_RXNE LL_SPI_SR_RXNE /*!< Rx buffer not empty flag */ +#define LL_I2S_SR_TXE LL_SPI_SR_TXE /*!< Tx buffer empty flag */ +#define LL_I2S_SR_BSY LL_SPI_SR_BSY /*!< Busy flag */ +#define LL_I2S_SR_UDR SPI_SR_UDR /*!< Underrun flag */ +#define LL_I2S_SR_OVR LL_SPI_SR_OVR /*!< Overrun flag */ +#define LL_I2S_SR_FRE LL_SPI_SR_FRE /*!< TI mode frame format error flag */ +/** + * @} + */ + +/** @defgroup SPI_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_SPI_ReadReg and LL_SPI_WriteReg functions + * @{ + */ +#define LL_I2S_CR2_RXNEIE LL_SPI_CR2_RXNEIE /*!< Rx buffer not empty interrupt enable */ +#define LL_I2S_CR2_TXEIE LL_SPI_CR2_TXEIE /*!< Tx buffer empty interrupt enable */ +#define LL_I2S_CR2_ERRIE LL_SPI_CR2_ERRIE /*!< Error interrupt enable */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_DATA_FORMAT Data format + * @{ + */ +#define LL_I2S_DATAFORMAT_16B 0x00000000U /*!< Data length 16 bits, Channel length 16bit */ +#define LL_I2S_DATAFORMAT_16B_EXTENDED (SPI_I2SCFGR_CHLEN) /*!< Data length 16 bits, Channel length 32bit */ +#define LL_I2S_DATAFORMAT_24B (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_0) /*!< Data length 24 bits, Channel length 32bit */ +#define LL_I2S_DATAFORMAT_32B (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN_1) /*!< Data length 16 bits, Channel length 32bit */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_I2S_POLARITY_LOW 0x00000000U /*!< Clock steady state is low level */ +#define LL_I2S_POLARITY_HIGH (SPI_I2SCFGR_CKPOL) /*!< Clock steady state is high level */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_STANDARD I2s Standard + * @{ + */ +#define LL_I2S_STANDARD_PHILIPS 0x00000000U /*!< I2S standard philips */ +#define LL_I2S_STANDARD_MSB (SPI_I2SCFGR_I2SSTD_0) /*!< MSB justified standard (left justified) */ +#define LL_I2S_STANDARD_LSB (SPI_I2SCFGR_I2SSTD_1) /*!< LSB justified standard (right justified) */ +#define LL_I2S_STANDARD_PCM_SHORT (SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1) /*!< PCM standard, short frame synchronization */ +#define LL_I2S_STANDARD_PCM_LONG (SPI_I2SCFGR_I2SSTD_0 | SPI_I2SCFGR_I2SSTD_1 | SPI_I2SCFGR_PCMSYNC) /*!< PCM standard, long frame synchronization */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_MODE Operation Mode + * @{ + */ +#define LL_I2S_MODE_SLAVE_TX 0x00000000U /*!< Slave Tx configuration */ +#define LL_I2S_MODE_SLAVE_RX (SPI_I2SCFGR_I2SCFG_0) /*!< Slave Rx configuration */ +#define LL_I2S_MODE_MASTER_TX (SPI_I2SCFGR_I2SCFG_1) /*!< Master Tx configuration */ +#define LL_I2S_MODE_MASTER_RX (SPI_I2SCFGR_I2SCFG_0 | SPI_I2SCFGR_I2SCFG_1) /*!< Master Rx configuration */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_PRESCALER_FACTOR Prescaler Factor + * @{ + */ +#define LL_I2S_PRESCALER_PARITY_EVEN 0x00000000U /*!< Odd factor: Real divider value is = I2SDIV * 2 */ +#define LL_I2S_PRESCALER_PARITY_ODD (SPI_I2SPR_ODD >> 8U) /*!< Odd factor: Real divider value is = (I2SDIV * 2)+1 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) + +/** @defgroup I2S_LL_EC_MCLK_OUTPUT MCLK Output + * @{ + */ +#define LL_I2S_MCLK_OUTPUT_DISABLE 0x00000000U /*!< Master clock output is disabled */ +#define LL_I2S_MCLK_OUTPUT_ENABLE (SPI_I2SPR_MCKOE) /*!< Master clock output is enabled */ +/** + * @} + */ + +/** @defgroup I2S_LL_EC_AUDIO_FREQ Audio Frequency + * @{ + */ + +#define LL_I2S_AUDIOFREQ_192K 192000U /*!< Audio Frequency configuration 192000 Hz */ +#define LL_I2S_AUDIOFREQ_96K 96000U /*!< Audio Frequency configuration 96000 Hz */ +#define LL_I2S_AUDIOFREQ_48K 48000U /*!< Audio Frequency configuration 48000 Hz */ +#define LL_I2S_AUDIOFREQ_44K 44100U /*!< Audio Frequency configuration 44100 Hz */ +#define LL_I2S_AUDIOFREQ_32K 32000U /*!< Audio Frequency configuration 32000 Hz */ +#define LL_I2S_AUDIOFREQ_22K 22050U /*!< Audio Frequency configuration 22050 Hz */ +#define LL_I2S_AUDIOFREQ_16K 16000U /*!< Audio Frequency configuration 16000 Hz */ +#define LL_I2S_AUDIOFREQ_11K 11025U /*!< Audio Frequency configuration 11025 Hz */ +#define LL_I2S_AUDIOFREQ_8K 8000U /*!< Audio Frequency configuration 8000 Hz */ +#define LL_I2S_AUDIOFREQ_DEFAULT 2U /*!< Audio Freq not specified. Register I2SDIV = 2 */ +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup I2S_LL_Exported_Macros I2S Exported Macros + * @{ + */ + +/** @defgroup I2S_LL_EM_WRITE_READ Common Write and read registers Macros + * @{ + */ + +/** + * @brief Write a value in I2S register + * @param __INSTANCE__ I2S Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_I2S_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in I2S register + * @param __INSTANCE__ I2S Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_I2S_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2S_LL_Exported_Functions I2S Exported Functions + * @{ + */ + +/** @defgroup I2S_LL_EF_Configuration Configuration + * @{ + */ + +/** + * @brief Select I2S mode and Enable I2S peripheral + * @rmtoll I2SCFGR I2SMOD LL_I2S_Enable\n + * I2SCFGR I2SE LL_I2S_Enable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_Enable(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE); +} + +/** + * @brief Disable I2S peripheral + * @rmtoll I2SCFGR I2SE LL_I2S_Disable + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_Disable(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE); +} + +/** + * @brief Check if I2S peripheral is enabled + * @rmtoll I2SCFGR I2SE LL_I2S_IsEnabled + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabled(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SE) == (SPI_I2SCFGR_I2SE)) ? 1UL : 0UL); +} + +/** + * @brief Set I2S data frame length + * @rmtoll I2SCFGR DATLEN LL_I2S_SetDataFormat\n + * I2SCFGR CHLEN LL_I2S_SetDataFormat + * @param SPIx SPI Instance + * @param DataFormat This parameter can be one of the following values: + * @arg @ref LL_I2S_DATAFORMAT_16B + * @arg @ref LL_I2S_DATAFORMAT_16B_EXTENDED + * @arg @ref LL_I2S_DATAFORMAT_24B + * @arg @ref LL_I2S_DATAFORMAT_32B + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetDataFormat(SPI_TypeDef *SPIx, uint32_t DataFormat) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN, DataFormat); +} + +/** + * @brief Get I2S data frame length + * @rmtoll I2SCFGR DATLEN LL_I2S_GetDataFormat\n + * I2SCFGR CHLEN LL_I2S_GetDataFormat + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_DATAFORMAT_16B + * @arg @ref LL_I2S_DATAFORMAT_16B_EXTENDED + * @arg @ref LL_I2S_DATAFORMAT_24B + * @arg @ref LL_I2S_DATAFORMAT_32B + */ +__STATIC_INLINE uint32_t LL_I2S_GetDataFormat(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN)); +} + +/** + * @brief Set I2S clock polarity + * @rmtoll I2SCFGR CKPOL LL_I2S_SetClockPolarity + * @param SPIx SPI Instance + * @param ClockPolarity This parameter can be one of the following values: + * @arg @ref LL_I2S_POLARITY_LOW + * @arg @ref LL_I2S_POLARITY_HIGH + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetClockPolarity(SPI_TypeDef *SPIx, uint32_t ClockPolarity) +{ + SET_BIT(SPIx->I2SCFGR, ClockPolarity); +} + +/** + * @brief Get I2S clock polarity + * @rmtoll I2SCFGR CKPOL LL_I2S_GetClockPolarity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_POLARITY_LOW + * @arg @ref LL_I2S_POLARITY_HIGH + */ +__STATIC_INLINE uint32_t LL_I2S_GetClockPolarity(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_CKPOL)); +} + +/** + * @brief Set I2S standard protocol + * @rmtoll I2SCFGR I2SSTD LL_I2S_SetStandard\n + * I2SCFGR PCMSYNC LL_I2S_SetStandard + * @param SPIx SPI Instance + * @param Standard This parameter can be one of the following values: + * @arg @ref LL_I2S_STANDARD_PHILIPS + * @arg @ref LL_I2S_STANDARD_MSB + * @arg @ref LL_I2S_STANDARD_LSB + * @arg @ref LL_I2S_STANDARD_PCM_SHORT + * @arg @ref LL_I2S_STANDARD_PCM_LONG + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetStandard(SPI_TypeDef *SPIx, uint32_t Standard) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC, Standard); +} + +/** + * @brief Get I2S standard protocol + * @rmtoll I2SCFGR I2SSTD LL_I2S_GetStandard\n + * I2SCFGR PCMSYNC LL_I2S_GetStandard + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_STANDARD_PHILIPS + * @arg @ref LL_I2S_STANDARD_MSB + * @arg @ref LL_I2S_STANDARD_LSB + * @arg @ref LL_I2S_STANDARD_PCM_SHORT + * @arg @ref LL_I2S_STANDARD_PCM_LONG + */ +__STATIC_INLINE uint32_t LL_I2S_GetStandard(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC)); +} + +/** + * @brief Set I2S transfer mode + * @rmtoll I2SCFGR I2SCFG LL_I2S_SetTransferMode + * @param SPIx SPI Instance + * @param Mode This parameter can be one of the following values: + * @arg @ref LL_I2S_MODE_SLAVE_TX + * @arg @ref LL_I2S_MODE_SLAVE_RX + * @arg @ref LL_I2S_MODE_MASTER_TX + * @arg @ref LL_I2S_MODE_MASTER_RX + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetTransferMode(SPI_TypeDef *SPIx, uint32_t Mode) +{ + MODIFY_REG(SPIx->I2SCFGR, SPI_I2SCFGR_I2SCFG, Mode); +} + +/** + * @brief Get I2S transfer mode + * @rmtoll I2SCFGR I2SCFG LL_I2S_GetTransferMode + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_MODE_SLAVE_TX + * @arg @ref LL_I2S_MODE_SLAVE_RX + * @arg @ref LL_I2S_MODE_MASTER_TX + * @arg @ref LL_I2S_MODE_MASTER_RX + */ +__STATIC_INLINE uint32_t LL_I2S_GetTransferMode(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SCFG)); +} + +/** + * @brief Set I2S linear prescaler + * @rmtoll I2SPR I2SDIV LL_I2S_SetPrescalerLinear + * @param SPIx SPI Instance + * @param PrescalerLinear Value between Min_Data=0x02 and Max_Data=0xFF + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetPrescalerLinear(SPI_TypeDef *SPIx, uint8_t PrescalerLinear) +{ + MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_I2SDIV, PrescalerLinear); +} + +/** + * @brief Get I2S linear prescaler + * @rmtoll I2SPR I2SDIV LL_I2S_GetPrescalerLinear + * @param SPIx SPI Instance + * @retval PrescalerLinear Value between Min_Data=0x02 and Max_Data=0xFF + */ +__STATIC_INLINE uint32_t LL_I2S_GetPrescalerLinear(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SPR, SPI_I2SPR_I2SDIV)); +} + +/** + * @brief Set I2S parity prescaler + * @rmtoll I2SPR ODD LL_I2S_SetPrescalerParity + * @param SPIx SPI Instance + * @param PrescalerParity This parameter can be one of the following values: + * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN + * @arg @ref LL_I2S_PRESCALER_PARITY_ODD + * @retval None + */ +__STATIC_INLINE void LL_I2S_SetPrescalerParity(SPI_TypeDef *SPIx, uint32_t PrescalerParity) +{ + MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_ODD, PrescalerParity << 8U); +} + +/** + * @brief Get I2S parity prescaler + * @rmtoll I2SPR ODD LL_I2S_GetPrescalerParity + * @param SPIx SPI Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN + * @arg @ref LL_I2S_PRESCALER_PARITY_ODD + */ +__STATIC_INLINE uint32_t LL_I2S_GetPrescalerParity(SPI_TypeDef *SPIx) +{ + return (uint32_t)(READ_BIT(SPIx->I2SPR, SPI_I2SPR_ODD) >> 8U); +} + +/** + * @brief Enable the master clock output (Pin MCK) + * @rmtoll I2SPR MCKOE LL_I2S_EnableMasterClock + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableMasterClock(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE); +} + +/** + * @brief Disable the master clock output (Pin MCK) + * @rmtoll I2SPR MCKOE LL_I2S_DisableMasterClock + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableMasterClock(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE); +} + +/** + * @brief Check if the master clock output (Pin MCK) is enabled + * @rmtoll I2SPR MCKOE LL_I2S_IsEnabledMasterClock + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledMasterClock(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->I2SPR, SPI_I2SPR_MCKOE) == (SPI_I2SPR_MCKOE)) ? 1UL : 0UL); +} + +#if defined(SPI_I2SCFGR_ASTRTEN) +/** + * @brief Enable asynchronous start + * @rmtoll I2SCFGR ASTRTEN LL_I2S_EnableAsyncStart + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableAsyncStart(SPI_TypeDef *SPIx) +{ + SET_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_ASTRTEN); +} + +/** + * @brief Disable asynchronous start + * @rmtoll I2SCFGR ASTRTEN LL_I2S_DisableAsyncStart + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableAsyncStart(SPI_TypeDef *SPIx) +{ + CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_ASTRTEN); +} + +/** + * @brief Check if asynchronous start is enabled + * @rmtoll I2SCFGR ASTRTEN LL_I2S_IsEnabledAsyncStart + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledAsyncStart(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_ASTRTEN) == (SPI_I2SCFGR_ASTRTEN)) ? 1UL : 0UL); +} +#endif /* SPI_I2SCFGR_ASTRTEN */ + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_FLAG FLAG Management + * @{ + */ + +/** + * @brief Check if Rx buffer is not empty + * @rmtoll SR RXNE LL_I2S_IsActiveFlag_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_RXNE(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_RXNE(SPIx); +} + +/** + * @brief Check if Tx buffer is empty + * @rmtoll SR TXE LL_I2S_IsActiveFlag_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_TXE(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_TXE(SPIx); +} + +/** + * @brief Get busy flag + * @rmtoll SR BSY LL_I2S_IsActiveFlag_BSY + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_BSY(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_BSY(SPIx); +} + +/** + * @brief Get overrun error flag + * @rmtoll SR OVR LL_I2S_IsActiveFlag_OVR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_OVR(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_OVR(SPIx); +} + +/** + * @brief Get underrun error flag + * @rmtoll SR UDR LL_I2S_IsActiveFlag_UDR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_UDR(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_UDR) == (SPI_SR_UDR)) ? 1UL : 0UL); +} + +/** + * @brief Get frame format error flag + * @rmtoll SR FRE LL_I2S_IsActiveFlag_FRE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_FRE(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsActiveFlag_FRE(SPIx); +} + +/** + * @brief Get channel side flag. + * @note 0: Channel Left has to be transmitted or has been received\n + * 1: Channel Right has to be transmitted or has been received\n + * It has no significance in PCM mode. + * @rmtoll SR CHSIDE LL_I2S_IsActiveFlag_CHSIDE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsActiveFlag_CHSIDE(SPI_TypeDef *SPIx) +{ + return ((READ_BIT(SPIx->SR, SPI_SR_CHSIDE) == (SPI_SR_CHSIDE)) ? 1UL : 0UL); +} + +/** + * @brief Clear overrun error flag + * @rmtoll SR OVR LL_I2S_ClearFlag_OVR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_OVR(SPI_TypeDef *SPIx) +{ + LL_SPI_ClearFlag_OVR(SPIx); +} + +/** + * @brief Clear underrun error flag + * @rmtoll SR UDR LL_I2S_ClearFlag_UDR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_UDR(SPI_TypeDef *SPIx) +{ + __IO uint32_t tmpreg; + tmpreg = SPIx->SR; + (void)tmpreg; +} + +/** + * @brief Clear frame format error flag + * @rmtoll SR FRE LL_I2S_ClearFlag_FRE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_ClearFlag_FRE(SPI_TypeDef *SPIx) +{ + LL_SPI_ClearFlag_FRE(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_IT Interrupt Management + * @{ + */ + +/** + * @brief Enable error IT + * @note This bit controls the generation of an interrupt when an error condition occurs (OVR, UDR and FRE in I2S mode). + * @rmtoll CR2 ERRIE LL_I2S_EnableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_ERR(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_ERR(SPIx); +} + +/** + * @brief Enable Rx buffer not empty IT + * @rmtoll CR2 RXNEIE LL_I2S_EnableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_RXNE(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_RXNE(SPIx); +} + +/** + * @brief Enable Tx buffer empty IT + * @rmtoll CR2 TXEIE LL_I2S_EnableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableIT_TXE(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableIT_TXE(SPIx); +} + +/** + * @brief Disable error IT + * @note This bit controls the generation of an interrupt when an error condition occurs (OVR, UDR and FRE in I2S mode). + * @rmtoll CR2 ERRIE LL_I2S_DisableIT_ERR + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_ERR(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_ERR(SPIx); +} + +/** + * @brief Disable Rx buffer not empty IT + * @rmtoll CR2 RXNEIE LL_I2S_DisableIT_RXNE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_RXNE(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_RXNE(SPIx); +} + +/** + * @brief Disable Tx buffer empty IT + * @rmtoll CR2 TXEIE LL_I2S_DisableIT_TXE + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableIT_TXE(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableIT_TXE(SPIx); +} + +/** + * @brief Check if ERR IT is enabled + * @rmtoll CR2 ERRIE LL_I2S_IsEnabledIT_ERR + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_ERR(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_ERR(SPIx); +} + +/** + * @brief Check if RXNE IT is enabled + * @rmtoll CR2 RXNEIE LL_I2S_IsEnabledIT_RXNE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_RXNE(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_RXNE(SPIx); +} + +/** + * @brief Check if TXE IT is enabled + * @rmtoll CR2 TXEIE LL_I2S_IsEnabledIT_TXE + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledIT_TXE(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledIT_TXE(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_DMA DMA Management + * @{ + */ + +/** + * @brief Enable DMA Rx + * @rmtoll CR2 RXDMAEN LL_I2S_EnableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableDMAReq_RX(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableDMAReq_RX(SPIx); +} + +/** + * @brief Disable DMA Rx + * @rmtoll CR2 RXDMAEN LL_I2S_DisableDMAReq_RX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableDMAReq_RX(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableDMAReq_RX(SPIx); +} + +/** + * @brief Check if DMA Rx is enabled + * @rmtoll CR2 RXDMAEN LL_I2S_IsEnabledDMAReq_RX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledDMAReq_RX(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledDMAReq_RX(SPIx); +} + +/** + * @brief Enable DMA Tx + * @rmtoll CR2 TXDMAEN LL_I2S_EnableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_EnableDMAReq_TX(SPI_TypeDef *SPIx) +{ + LL_SPI_EnableDMAReq_TX(SPIx); +} + +/** + * @brief Disable DMA Tx + * @rmtoll CR2 TXDMAEN LL_I2S_DisableDMAReq_TX + * @param SPIx SPI Instance + * @retval None + */ +__STATIC_INLINE void LL_I2S_DisableDMAReq_TX(SPI_TypeDef *SPIx) +{ + LL_SPI_DisableDMAReq_TX(SPIx); +} + +/** + * @brief Check if DMA Tx is enabled + * @rmtoll CR2 TXDMAEN LL_I2S_IsEnabledDMAReq_TX + * @param SPIx SPI Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_I2S_IsEnabledDMAReq_TX(SPI_TypeDef *SPIx) +{ + return LL_SPI_IsEnabledDMAReq_TX(SPIx); +} + +/** + * @} + */ + +/** @defgroup I2S_LL_EF_DATA DATA Management + * @{ + */ + +/** + * @brief Read 16-Bits in data register + * @rmtoll DR DR LL_I2S_ReceiveData16 + * @param SPIx SPI Instance + * @retval RxData Value between Min_Data=0x0000 and Max_Data=0xFFFF + */ +__STATIC_INLINE uint16_t LL_I2S_ReceiveData16(SPI_TypeDef *SPIx) +{ + return LL_SPI_ReceiveData16(SPIx); +} + +/** + * @brief Write 16-Bits in data register + * @rmtoll DR DR LL_I2S_TransmitData16 + * @param SPIx SPI Instance + * @param TxData Value between Min_Data=0x0000 and Max_Data=0xFFFF + * @retval None + */ +__STATIC_INLINE void LL_I2S_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData) +{ + LL_SPI_TransmitData16(SPIx, TxData); +} + +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup I2S_LL_EF_Init Initialization and de-initialization functions + * @{ + */ + +ErrorStatus LL_I2S_DeInit(SPI_TypeDef *SPIx); +ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct); +void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct); +void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity); +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) +ErrorStatus LL_I2S_InitFullDuplex(SPI_TypeDef *I2Sxext, LL_I2S_InitTypeDef *I2S_InitStruct); +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + +/** + * @} + */ +#endif /* USE_FULL_LL_DRIVER */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4) || defined (SPI5) || defined(SPI6) */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_SPI_H */ + diff --git a/libs/hal/stm32f4xx_ll_system.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h similarity index 100% rename from libs/hal/stm32f4xx_ll_system.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_system.h diff --git a/libs/hal/stm32f4xx_ll_tim.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h similarity index 97% rename from libs/hal/stm32f4xx_ll_tim.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h index 61148e4..a5cbe24 100644 --- a/libs/hal/stm32f4xx_ll_tim.h +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_tim.h @@ -1143,7 +1143,7 @@ __STATIC_INLINE void LL_TIM_DisableCounter(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledCounter(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledCounter(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->CR1, TIM_CR1_CEN) == (TIM_CR1_CEN)) ? 1UL : 0UL); } @@ -1176,7 +1176,7 @@ __STATIC_INLINE void LL_TIM_DisableUpdateEvent(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval Inverted state of bit (0 or 1). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledUpdateEvent(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledUpdateEvent(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->CR1, TIM_CR1_UDIS) == (uint32_t)RESET) ? 1UL : 0UL); } @@ -1210,7 +1210,7 @@ __STATIC_INLINE void LL_TIM_SetUpdateSource(TIM_TypeDef *TIMx, uint32_t UpdateSo * @arg @ref LL_TIM_UPDATESOURCE_REGULAR * @arg @ref LL_TIM_UPDATESOURCE_COUNTER */ -__STATIC_INLINE uint32_t LL_TIM_GetUpdateSource(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetUpdateSource(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_URS)); } @@ -1237,7 +1237,7 @@ __STATIC_INLINE void LL_TIM_SetOnePulseMode(TIM_TypeDef *TIMx, uint32_t OnePulse * @arg @ref LL_TIM_ONEPULSEMODE_SINGLE * @arg @ref LL_TIM_ONEPULSEMODE_REPETITIVE */ -__STATIC_INLINE uint32_t LL_TIM_GetOnePulseMode(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetOnePulseMode(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_OPM)); } @@ -1281,7 +1281,7 @@ __STATIC_INLINE void LL_TIM_SetCounterMode(TIM_TypeDef *TIMx, uint32_t CounterMo * @arg @ref LL_TIM_COUNTERMODE_CENTER_DOWN * @arg @ref LL_TIM_COUNTERMODE_CENTER_UP_DOWN */ -__STATIC_INLINE uint32_t LL_TIM_GetCounterMode(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetCounterMode(const TIM_TypeDef *TIMx) { uint32_t counter_mode; @@ -1323,7 +1323,7 @@ __STATIC_INLINE void LL_TIM_DisableARRPreload(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledARRPreload(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledARRPreload(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->CR1, TIM_CR1_ARPE) == (TIM_CR1_ARPE)) ? 1UL : 0UL); } @@ -1360,7 +1360,7 @@ __STATIC_INLINE void LL_TIM_SetClockDivision(TIM_TypeDef *TIMx, uint32_t ClockDi * @arg @ref LL_TIM_CLOCKDIVISION_DIV2 * @arg @ref LL_TIM_CLOCKDIVISION_DIV4 */ -__STATIC_INLINE uint32_t LL_TIM_GetClockDivision(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetClockDivision(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_CKD)); } @@ -1387,7 +1387,7 @@ __STATIC_INLINE void LL_TIM_SetCounter(TIM_TypeDef *TIMx, uint32_t Counter) * @param TIMx Timer instance * @retval Counter value (between Min_Data=0 and Max_Data=0xFFFF or 0xFFFFFFFF) */ -__STATIC_INLINE uint32_t LL_TIM_GetCounter(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetCounter(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CNT)); } @@ -1400,7 +1400,7 @@ __STATIC_INLINE uint32_t LL_TIM_GetCounter(TIM_TypeDef *TIMx) * @arg @ref LL_TIM_COUNTERDIRECTION_UP * @arg @ref LL_TIM_COUNTERDIRECTION_DOWN */ -__STATIC_INLINE uint32_t LL_TIM_GetDirection(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetDirection(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_BIT(TIMx->CR1, TIM_CR1_DIR)); } @@ -1427,7 +1427,7 @@ __STATIC_INLINE void LL_TIM_SetPrescaler(TIM_TypeDef *TIMx, uint32_t Prescaler) * @param TIMx Timer instance * @retval Prescaler value between Min_Data=0 and Max_Data=65535 */ -__STATIC_INLINE uint32_t LL_TIM_GetPrescaler(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetPrescaler(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->PSC)); } @@ -1456,7 +1456,7 @@ __STATIC_INLINE void LL_TIM_SetAutoReload(TIM_TypeDef *TIMx, uint32_t AutoReload * @param TIMx Timer instance * @retval Auto-reload value */ -__STATIC_INLINE uint32_t LL_TIM_GetAutoReload(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetAutoReload(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->ARR)); } @@ -1483,7 +1483,7 @@ __STATIC_INLINE void LL_TIM_SetRepetitionCounter(TIM_TypeDef *TIMx, uint32_t Rep * @param TIMx Timer instance * @retval Repetition counter value */ -__STATIC_INLINE uint32_t LL_TIM_GetRepetitionCounter(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_GetRepetitionCounter(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->RCR)); } @@ -1562,7 +1562,7 @@ __STATIC_INLINE void LL_TIM_CC_SetDMAReqTrigger(TIM_TypeDef *TIMx, uint32_t DMAR * @arg @ref LL_TIM_CCDMAREQUEST_CC * @arg @ref LL_TIM_CCDMAREQUEST_UPDATE */ -__STATIC_INLINE uint32_t LL_TIM_CC_GetDMAReqTrigger(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_CC_GetDMAReqTrigger(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_BIT(TIMx->CR2, TIM_CR2_CCDS)); } @@ -1757,7 +1757,7 @@ __STATIC_INLINE void LL_TIM_OC_SetMode(TIM_TypeDef *TIMx, uint32_t Channel, uint * @arg @ref LL_TIM_OCMODE_PWM1 * @arg @ref LL_TIM_OCMODE_PWM2 */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetMode(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_OC_GetMode(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); const __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); @@ -1815,7 +1815,7 @@ __STATIC_INLINE void LL_TIM_OC_SetPolarity(TIM_TypeDef *TIMx, uint32_t Channel, * @arg @ref LL_TIM_OCPOLARITY_HIGH * @arg @ref LL_TIM_OCPOLARITY_LOW */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetPolarity(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_OC_GetPolarity(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); return (READ_BIT(TIMx->CCER, (TIM_CCER_CC1P << SHIFT_TAB_CCxP[iChannel])) >> SHIFT_TAB_CCxP[iChannel]); @@ -1876,7 +1876,7 @@ __STATIC_INLINE void LL_TIM_OC_SetIdleState(TIM_TypeDef *TIMx, uint32_t Channel, * @arg @ref LL_TIM_OCIDLESTATE_LOW * @arg @ref LL_TIM_OCIDLESTATE_HIGH */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetIdleState(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_OC_GetIdleState(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); return (READ_BIT(TIMx->CR2, (TIM_CR2_OIS1 << SHIFT_TAB_OISx[iChannel])) >> SHIFT_TAB_OISx[iChannel]); @@ -2181,7 +2181,7 @@ __STATIC_INLINE void LL_TIM_OC_SetCompareCH4(TIM_TypeDef *TIMx, uint32_t Compare * @param TIMx Timer instance * @retval CompareValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH1(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH1(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR1)); } @@ -2197,7 +2197,7 @@ __STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH1(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CompareValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH2(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH2(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR2)); } @@ -2213,7 +2213,7 @@ __STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH2(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CompareValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH3(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH3(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR3)); } @@ -2229,7 +2229,7 @@ __STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH3(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CompareValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH4(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_OC_GetCompareCH4(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR4)); } @@ -2329,7 +2329,7 @@ __STATIC_INLINE void LL_TIM_IC_SetActiveInput(TIM_TypeDef *TIMx, uint32_t Channe * @arg @ref LL_TIM_ACTIVEINPUT_INDIRECTTI * @arg @ref LL_TIM_ACTIVEINPUT_TRC */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetActiveInput(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_IC_GetActiveInput(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); const __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); @@ -2380,7 +2380,7 @@ __STATIC_INLINE void LL_TIM_IC_SetPrescaler(TIM_TypeDef *TIMx, uint32_t Channel, * @arg @ref LL_TIM_ICPSC_DIV4 * @arg @ref LL_TIM_ICPSC_DIV8 */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetPrescaler(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_IC_GetPrescaler(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); const __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); @@ -2455,7 +2455,7 @@ __STATIC_INLINE void LL_TIM_IC_SetFilter(TIM_TypeDef *TIMx, uint32_t Channel, ui * @arg @ref LL_TIM_IC_FILTER_FDIV32_N6 * @arg @ref LL_TIM_IC_FILTER_FDIV32_N8 */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetFilter(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_IC_GetFilter(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); const __IO uint32_t *pReg = (__IO uint32_t *)((uint32_t)((uint32_t)(&TIMx->CCMR1) + OFFSET_TAB_CCMRx[iChannel])); @@ -2512,7 +2512,7 @@ __STATIC_INLINE void LL_TIM_IC_SetPolarity(TIM_TypeDef *TIMx, uint32_t Channel, * @arg @ref LL_TIM_IC_POLARITY_FALLING * @arg @ref LL_TIM_IC_POLARITY_BOTHEDGE */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetPolarity(TIM_TypeDef *TIMx, uint32_t Channel) +__STATIC_INLINE uint32_t LL_TIM_IC_GetPolarity(const TIM_TypeDef *TIMx, uint32_t Channel) { uint8_t iChannel = TIM_GET_CHANNEL_INDEX(Channel); return (READ_BIT(TIMx->CCER, ((TIM_CCER_CC1NP | TIM_CCER_CC1P) << SHIFT_TAB_CCxP[iChannel])) >> @@ -2569,7 +2569,7 @@ __STATIC_INLINE uint32_t LL_TIM_IC_IsEnabledXORCombination(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH1(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH1(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR1)); } @@ -2585,7 +2585,7 @@ __STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH1(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH2(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH2(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR2)); } @@ -2601,7 +2601,7 @@ __STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH2(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH3(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH3(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR3)); } @@ -2617,7 +2617,7 @@ __STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH3(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval CapturedValue (between Min_Data=0 and Max_Data=65535) */ -__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH4(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IC_GetCaptureCH4(const TIM_TypeDef *TIMx) { return (uint32_t)(READ_REG(TIMx->CCR4)); } @@ -2664,7 +2664,7 @@ __STATIC_INLINE void LL_TIM_DisableExternalClock(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledExternalClock(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledExternalClock(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SMCR, TIM_SMCR_ECE) == (TIM_SMCR_ECE)) ? 1UL : 0UL); } @@ -2813,7 +2813,7 @@ __STATIC_INLINE void LL_TIM_DisableMasterSlaveMode(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledMasterSlaveMode(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledMasterSlaveMode(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SMCR, TIM_SMCR_MSM) == (TIM_SMCR_MSM)) ? 1UL : 0UL); } @@ -2974,7 +2974,7 @@ __STATIC_INLINE void LL_TIM_DisableAutomaticOutput(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledAutomaticOutput(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledAutomaticOutput(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->BDTR, TIM_BDTR_AOE) == (TIM_BDTR_AOE)) ? 1UL : 0UL); } @@ -3017,7 +3017,7 @@ __STATIC_INLINE void LL_TIM_DisableAllOutputs(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledAllOutputs(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledAllOutputs(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->BDTR, TIM_BDTR_MOE) == (TIM_BDTR_MOE)) ? 1UL : 0UL); } @@ -3190,7 +3190,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_UPDATE(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_UPDATE(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_UPDATE(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_UIF) == (TIM_SR_UIF)) ? 1UL : 0UL); } @@ -3212,7 +3212,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC1(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC1(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC1(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC1IF) == (TIM_SR_CC1IF)) ? 1UL : 0UL); } @@ -3234,7 +3234,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC2(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC2(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC2(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC2IF) == (TIM_SR_CC2IF)) ? 1UL : 0UL); } @@ -3256,7 +3256,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC3(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC3(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC3(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC3IF) == (TIM_SR_CC3IF)) ? 1UL : 0UL); } @@ -3278,7 +3278,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC4(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC4(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC4(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC4IF) == (TIM_SR_CC4IF)) ? 1UL : 0UL); } @@ -3300,7 +3300,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_COM(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_COM(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_COM(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_COMIF) == (TIM_SR_COMIF)) ? 1UL : 0UL); } @@ -3322,7 +3322,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_TRIG(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_TRIG(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_TRIG(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_TIF) == (TIM_SR_TIF)) ? 1UL : 0UL); } @@ -3344,7 +3344,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_BRK(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_BRK(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_BRK(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_BIF) == (TIM_SR_BIF)) ? 1UL : 0UL); } @@ -3367,7 +3367,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC1OVR(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC1OVR(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC1OVR(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC1OF) == (TIM_SR_CC1OF)) ? 1UL : 0UL); } @@ -3390,7 +3390,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC2OVR(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC2OVR(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC2OVR(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC2OF) == (TIM_SR_CC2OF)) ? 1UL : 0UL); } @@ -3413,7 +3413,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC3OVR(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC3OVR(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC3OVR(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC3OF) == (TIM_SR_CC3OF)) ? 1UL : 0UL); } @@ -3436,7 +3436,7 @@ __STATIC_INLINE void LL_TIM_ClearFlag_CC4OVR(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC4OVR(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsActiveFlag_CC4OVR(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->SR, TIM_SR_CC4OF) == (TIM_SR_CC4OF)) ? 1UL : 0UL); } @@ -3476,7 +3476,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_UPDATE(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_UPDATE(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_UPDATE(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_UIE) == (TIM_DIER_UIE)) ? 1UL : 0UL); } @@ -3509,7 +3509,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_CC1(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC1(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC1(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC1IE) == (TIM_DIER_CC1IE)) ? 1UL : 0UL); } @@ -3542,7 +3542,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_CC2(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC2(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC2(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC2IE) == (TIM_DIER_CC2IE)) ? 1UL : 0UL); } @@ -3575,7 +3575,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_CC3(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC3(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC3(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC3IE) == (TIM_DIER_CC3IE)) ? 1UL : 0UL); } @@ -3608,7 +3608,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_CC4(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC4(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_CC4(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC4IE) == (TIM_DIER_CC4IE)) ? 1UL : 0UL); } @@ -3641,7 +3641,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_COM(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_COM(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_COM(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_COMIE) == (TIM_DIER_COMIE)) ? 1UL : 0UL); } @@ -3674,7 +3674,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_TRIG(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_TRIG(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_TRIG(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_TIE) == (TIM_DIER_TIE)) ? 1UL : 0UL); } @@ -3707,7 +3707,7 @@ __STATIC_INLINE void LL_TIM_DisableIT_BRK(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_BRK(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledIT_BRK(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_BIE) == (TIM_DIER_BIE)) ? 1UL : 0UL); } @@ -3747,7 +3747,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_UPDATE(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_UPDATE(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_UPDATE(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_UDE) == (TIM_DIER_UDE)) ? 1UL : 0UL); } @@ -3780,7 +3780,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_CC1(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC1(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC1(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC1DE) == (TIM_DIER_CC1DE)) ? 1UL : 0UL); } @@ -3813,7 +3813,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_CC2(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC2(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC2(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC2DE) == (TIM_DIER_CC2DE)) ? 1UL : 0UL); } @@ -3846,7 +3846,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_CC3(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC3(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC3(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC3DE) == (TIM_DIER_CC3DE)) ? 1UL : 0UL); } @@ -3879,7 +3879,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_CC4(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC4(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_CC4(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_CC4DE) == (TIM_DIER_CC4DE)) ? 1UL : 0UL); } @@ -3912,7 +3912,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_COM(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_COM(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_COM(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_COMDE) == (TIM_DIER_COMDE)) ? 1UL : 0UL); } @@ -3945,7 +3945,7 @@ __STATIC_INLINE void LL_TIM_DisableDMAReq_TRIG(TIM_TypeDef *TIMx) * @param TIMx Timer instance * @retval State of bit (1 or 0). */ -__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_TRIG(TIM_TypeDef *TIMx) +__STATIC_INLINE uint32_t LL_TIM_IsEnabledDMAReq_TRIG(const TIM_TypeDef *TIMx) { return ((READ_BIT(TIMx->DIER, TIM_DIER_TDE) == (TIM_DIER_TDE)) ? 1UL : 0UL); } @@ -4056,17 +4056,17 @@ __STATIC_INLINE void LL_TIM_GenerateEvent_BRK(TIM_TypeDef *TIMx) ErrorStatus LL_TIM_DeInit(TIM_TypeDef *TIMx); void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct); -ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, LL_TIM_InitTypeDef *TIM_InitStruct); +ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, const LL_TIM_InitTypeDef *TIM_InitStruct); void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct); -ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct); +ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct); void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct); -ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct); +ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct); void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct); -ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct); +ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, const LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct); void LL_TIM_HALLSENSOR_StructInit(LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct); -ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct); +ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, const LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct); void LL_TIM_BDTR_StructInit(LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct); -ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct); +ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, const LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct); /** * @} */ diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h new file mode 100644 index 0000000..14b9cb6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usart.h @@ -0,0 +1,2521 @@ +/** + ****************************************************************************** + * @file stm32f4xx_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 __STM32F4xx_LL_USART_H +#define __STM32F4xx_LL_USART_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (USART1) || defined (USART2) || defined (USART3) || defined (USART6) || defined (UART4) || defined (UART5) || defined (UART7) || defined (UART8) || defined (UART9) || defined (UART10) + +/** @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 */ +#define LL_USART_OVERSAMPLING_8 USART_CR1_OVER8 /*!< Oversampling by 8 */ +/** + * @} + */ + +#if defined(USE_FULL_LL_DRIVER) +/** @defgroup USART_LL_EC_CLOCK Clock Signal + * @{ + */ + +#define LL_USART_CLOCK_DISABLE 0x00000000U /*!< Clock signal not provided */ +#define LL_USART_CLOCK_ENABLE USART_CR2_CLKEN /*!< Clock signal provided */ +/** + * @} + */ +#endif /*USE_FULL_LL_DRIVER*/ + +/** @defgroup USART_LL_EC_LASTCLKPULSE Last Clock Pulse + * @{ + */ +#define LL_USART_LASTCLKPULSE_NO_OUTPUT 0x00000000U /*!< The clock pulse of the last data bit is not output to the SCLK pin */ +#define LL_USART_LASTCLKPULSE_OUTPUT USART_CR2_LBCL /*!< The clock pulse of the last data bit is output to the SCLK pin */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_PHASE Clock Phase + * @{ + */ +#define LL_USART_PHASE_1EDGE 0x00000000U /*!< The first clock transition is the first data capture edge */ +#define LL_USART_PHASE_2EDGE USART_CR2_CPHA /*!< The second clock transition is the first data capture edge */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_POLARITY Clock Polarity + * @{ + */ +#define LL_USART_POLARITY_LOW 0x00000000U /*!< Steady low value on SCLK pin outside transmission window*/ +#define LL_USART_POLARITY_HIGH USART_CR2_CPOL /*!< Steady high value on SCLK pin outside transmission window */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_STOPBITS Stop Bits + * @{ + */ +#define LL_USART_STOPBITS_0_5 USART_CR2_STOP_0 /*!< 0.5 stop bit */ +#define LL_USART_STOPBITS_1 0x00000000U /*!< 1 stop bit */ +#define LL_USART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) /*!< 1.5 stop bits */ +#define LL_USART_STOPBITS_2 USART_CR2_STOP_1 /*!< 2 stop bits */ +/** + * @} + */ + +/** @defgroup USART_LL_EC_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__) ((uint32_t)((((uint64_t)(__PERIPHCLK__))*25)/(2*((uint64_t)(__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__) ((uint32_t)((((uint64_t)(__PERIPHCLK__))*25)/(4*((uint64_t)(__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)); +} + +/** + * @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)); +} + +/** + * @brief Configure if Clock pulse of the last data bit is output to the SCLK pin or not + * @note Macro @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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)); +} + +/** + * @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)); +} + +/** + * @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); +} + +/** + * @} + */ + +/** @defgroup USART_LL_EF_Configuration_IRDA Configuration functions related to Irda feature + * @{ + */ + +/** + * @brief Enable IrDA mode + * @note Macro @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 @ref 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 || USART6 || UART4 || UART5 || UART7 || UART8 || UART9 || UART10 */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4xx_LL_USART_H */ + diff --git a/libs/hal/stm32f4xx_ll_usb.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h similarity index 100% rename from libs/hal/stm32f4xx_ll_usb.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_usb.h diff --git a/libs/hal/stm32f4xx_ll_utils.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h similarity index 100% rename from libs/hal/stm32f4xx_ll_utils.h rename to libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_utils.h diff --git a/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h new file mode 100644 index 0000000..5cbca0d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Inc/stm32f4xx_ll_wwdg.h @@ -0,0 +1,316 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_wwdg.h + * @author MCD Application Team + * @brief Header file of WWDG 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 STM32F4xx_LL_WWDG_H +#define STM32F4xx_LL_WWDG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (WWDG) + +/** @defgroup WWDG_LL WWDG + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup WWDG_LL_Exported_Constants WWDG Exported Constants + * @{ + */ + +/** @defgroup WWDG_LL_EC_IT IT Defines + * @brief IT defines which can be used with LL_WWDG_ReadReg and LL_WWDG_WriteReg functions + * @{ + */ +#define LL_WWDG_CFR_EWI WWDG_CFR_EWI +/** + * @} + */ + +/** @defgroup WWDG_LL_EC_PRESCALER PRESCALER + * @{ + */ +#define LL_WWDG_PRESCALER_1 0x00000000u /*!< WWDG counter clock = (PCLK1/4096)/1 */ +#define LL_WWDG_PRESCALER_2 WWDG_CFR_WDGTB_0 /*!< WWDG counter clock = (PCLK1/4096)/2 */ +#define LL_WWDG_PRESCALER_4 WWDG_CFR_WDGTB_1 /*!< WWDG counter clock = (PCLK1/4096)/4 */ +#define LL_WWDG_PRESCALER_8 (WWDG_CFR_WDGTB_0 | WWDG_CFR_WDGTB_1) /*!< WWDG counter clock = (PCLK1/4096)/8 */ +/** + * @} + */ + +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/** @defgroup WWDG_LL_Exported_Macros WWDG Exported Macros + * @{ + */ +/** @defgroup WWDG_LL_EM_WRITE_READ Common Write and read registers macros + * @{ + */ +/** + * @brief Write a value in WWDG register + * @param __INSTANCE__ WWDG Instance + * @param __REG__ Register to be written + * @param __VALUE__ Value to be written in the register + * @retval None + */ +#define LL_WWDG_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__)) + +/** + * @brief Read a value in WWDG register + * @param __INSTANCE__ WWDG Instance + * @param __REG__ Register to be read + * @retval Register value + */ +#define LL_WWDG_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__) +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup WWDG_LL_Exported_Functions WWDG Exported Functions + * @{ + */ + +/** @defgroup WWDG_LL_EF_Configuration Configuration + * @{ + */ +/** + * @brief Enable Window Watchdog. The watchdog is always disabled after a reset. + * @note It is enabled by setting the WDGA bit in the WWDG_CR register, + * then it cannot be disabled again except by a reset. + * This bit is set by software and only cleared by hardware after a reset. + * When WDGA = 1, the watchdog can generate a reset. + * @rmtoll CR WDGA LL_WWDG_Enable + * @param WWDGx WWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_WWDG_Enable(WWDG_TypeDef *WWDGx) +{ + SET_BIT(WWDGx->CR, WWDG_CR_WDGA); +} + +/** + * @brief Checks if Window Watchdog is enabled + * @rmtoll CR WDGA LL_WWDG_IsEnabled + * @param WWDGx WWDG Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_WWDG_IsEnabled(WWDG_TypeDef *WWDGx) +{ + return ((READ_BIT(WWDGx->CR, WWDG_CR_WDGA) == (WWDG_CR_WDGA)) ? 1UL : 0UL); +} + +/** + * @brief Set the Watchdog counter value to provided value (7-bits T[6:0]) + * @note When writing to the WWDG_CR register, always write 1 in the MSB b6 to avoid generating an immediate reset + * This counter is decremented every (4096 x 2expWDGTB) PCLK cycles + * A reset is produced when it rolls over from 0x40 to 0x3F (bit T6 becomes cleared) + * Setting the counter lower then 0x40 causes an immediate reset (if WWDG enabled) + * @rmtoll CR T LL_WWDG_SetCounter + * @param WWDGx WWDG Instance + * @param Counter 0..0x7F (7 bit counter value) + * @retval None + */ +__STATIC_INLINE void LL_WWDG_SetCounter(WWDG_TypeDef *WWDGx, uint32_t Counter) +{ + MODIFY_REG(WWDGx->CR, WWDG_CR_T, Counter); +} + +/** + * @brief Return current Watchdog Counter Value (7 bits counter value) + * @rmtoll CR T LL_WWDG_GetCounter + * @param WWDGx WWDG Instance + * @retval 7 bit Watchdog Counter value + */ +__STATIC_INLINE uint32_t LL_WWDG_GetCounter(WWDG_TypeDef *WWDGx) +{ + return (READ_BIT(WWDGx->CR, WWDG_CR_T)); +} + +/** + * @brief Set the time base of the prescaler (WDGTB). + * @note Prescaler is used to apply ratio on PCLK clock, so that Watchdog counter + * is decremented every (4096 x 2expWDGTB) PCLK cycles + * @rmtoll CFR WDGTB LL_WWDG_SetPrescaler + * @param WWDGx WWDG Instance + * @param Prescaler This parameter can be one of the following values: + * @arg @ref LL_WWDG_PRESCALER_1 + * @arg @ref LL_WWDG_PRESCALER_2 + * @arg @ref LL_WWDG_PRESCALER_4 + * @arg @ref LL_WWDG_PRESCALER_8 + * @retval None + */ +__STATIC_INLINE void LL_WWDG_SetPrescaler(WWDG_TypeDef *WWDGx, uint32_t Prescaler) +{ + MODIFY_REG(WWDGx->CFR, WWDG_CFR_WDGTB, Prescaler); +} + +/** + * @brief Return current Watchdog Prescaler Value + * @rmtoll CFR WDGTB LL_WWDG_GetPrescaler + * @param WWDGx WWDG Instance + * @retval Returned value can be one of the following values: + * @arg @ref LL_WWDG_PRESCALER_1 + * @arg @ref LL_WWDG_PRESCALER_2 + * @arg @ref LL_WWDG_PRESCALER_4 + * @arg @ref LL_WWDG_PRESCALER_8 + */ +__STATIC_INLINE uint32_t LL_WWDG_GetPrescaler(WWDG_TypeDef *WWDGx) +{ + return (READ_BIT(WWDGx->CFR, WWDG_CFR_WDGTB)); +} + +/** + * @brief Set the Watchdog Window value to be compared to the downcounter (7-bits W[6:0]). + * @note This window value defines when write in the WWDG_CR register + * to program Watchdog counter is allowed. + * Watchdog counter value update must occur only when the counter value + * is lower than the Watchdog window register value. + * Otherwise, a MCU reset is generated if the 7-bit Watchdog counter value + * (in the control register) is refreshed before the downcounter has reached + * the watchdog window register value. + * Physically is possible to set the Window lower then 0x40 but it is not recommended. + * To generate an immediate reset, it is possible to set the Counter lower than 0x40. + * @rmtoll CFR W LL_WWDG_SetWindow + * @param WWDGx WWDG Instance + * @param Window 0x00..0x7F (7 bit Window value) + * @retval None + */ +__STATIC_INLINE void LL_WWDG_SetWindow(WWDG_TypeDef *WWDGx, uint32_t Window) +{ + MODIFY_REG(WWDGx->CFR, WWDG_CFR_W, Window); +} + +/** + * @brief Return current Watchdog Window Value (7 bits value) + * @rmtoll CFR W LL_WWDG_GetWindow + * @param WWDGx WWDG Instance + * @retval 7 bit Watchdog Window value + */ +__STATIC_INLINE uint32_t LL_WWDG_GetWindow(WWDG_TypeDef *WWDGx) +{ + return (READ_BIT(WWDGx->CFR, WWDG_CFR_W)); +} + +/** + * @} + */ + +/** @defgroup WWDG_LL_EF_FLAG_Management FLAG_Management + * @{ + */ +/** + * @brief Indicates if the WWDG Early Wakeup Interrupt Flag is set or not. + * @note This bit is set by hardware when the counter has reached the value 0x40. + * It must be cleared by software by writing 0. + * A write of 1 has no effect. This bit is also set if the interrupt is not enabled. + * @rmtoll SR EWIF LL_WWDG_IsActiveFlag_EWKUP + * @param WWDGx WWDG Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_WWDG_IsActiveFlag_EWKUP(WWDG_TypeDef *WWDGx) +{ + return ((READ_BIT(WWDGx->SR, WWDG_SR_EWIF) == (WWDG_SR_EWIF)) ? 1UL : 0UL); +} + +/** + * @brief Clear WWDG Early Wakeup Interrupt Flag (EWIF) + * @rmtoll SR EWIF LL_WWDG_ClearFlag_EWKUP + * @param WWDGx WWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_WWDG_ClearFlag_EWKUP(WWDG_TypeDef *WWDGx) +{ + WRITE_REG(WWDGx->SR, ~WWDG_SR_EWIF); +} + +/** + * @} + */ + +/** @defgroup WWDG_LL_EF_IT_Management IT_Management + * @{ + */ +/** + * @brief Enable the Early Wakeup Interrupt. + * @note When set, an interrupt occurs whenever the counter reaches value 0x40. + * This interrupt is only cleared by hardware after a reset + * @rmtoll CFR EWI LL_WWDG_EnableIT_EWKUP + * @param WWDGx WWDG Instance + * @retval None + */ +__STATIC_INLINE void LL_WWDG_EnableIT_EWKUP(WWDG_TypeDef *WWDGx) +{ + SET_BIT(WWDGx->CFR, WWDG_CFR_EWI); +} + +/** + * @brief Check if Early Wakeup Interrupt is enabled + * @rmtoll CFR EWI LL_WWDG_IsEnabledIT_EWKUP + * @param WWDGx WWDG Instance + * @retval State of bit (1 or 0). + */ +__STATIC_INLINE uint32_t LL_WWDG_IsEnabledIT_EWKUP(WWDG_TypeDef *WWDGx) +{ + return ((READ_BIT(WWDGx->CFR, WWDG_CFR_EWI) == (WWDG_CFR_EWI)) ? 1UL : 0UL); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* WWDG */ + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_LL_WWDG_H */ diff --git a/libs/STM32F4xx_HAL_Driver/LICENSE.md b/libs/STM32F4xx_HAL_Driver/LICENSE.md new file mode 100644 index 0000000..479c4f6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/LICENSE.md @@ -0,0 +1,27 @@ +Copyright 2017 STMicroelectronics. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/STM32F4xx_HAL_Driver/README.md b/libs/STM32F4xx_HAL_Driver/README.md new file mode 100644 index 0000000..5900a11 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/README.md @@ -0,0 +1,38 @@ +# STM32CubeF4 HAL Driver MCU Component + +![latest tag](https://img.shields.io/github/v/tag/STMicroelectronics/stm32f4xx_hal_driver.svg?color=brightgreen) + +## Overview + +**STM32Cube** is an STMicroelectronics original initiative to ease developers' life by reducing efforts, time and cost. + +**STM32Cube** covers the overall STM32 products portfolio. It includes a comprehensive embedded software platform delivered for each STM32 series. + * The CMSIS modules (core and device) corresponding to the ARM(tm) core implemented in this STM32 product. + * The STM32 HAL-LL drivers, an abstraction layer offering a set of APIs ensuring maximized portability across the STM32 portfolio. + * The BSP drivers of each evaluation, demonstration or nucleo board provided for this STM32 series. + * A consistent set of middleware libraries such as RTOS, USB, FatFS, graphics, touch sensing library... + * A full set of software projects (basic examples, applications, and demonstrations) for each board provided for this STM32 series. + +Two models of publication are proposed for the STM32Cube embedded software: + * The monolithic **MCU Package**: all STM32Cube software modules of one STM32 series are present (Drivers, Middleware, Projects, Utilities) in the repository (usual name **STM32Cubexx**, xx corresponding to the STM32 series). + * The **MCU component**: each STM32Cube software module being part of the STM32Cube MCU Package, is delivered as an individual repository, allowing the user to select and get only the required software functions. + +## Description + +This **stm32f4xx_hal_driver** MCU component repository is one element of the STM32CubeF4 MCU embedded software package, providing the **HAL-LL Drivers** part. + +## Release note + +Details about the content of this release are available in the release note [here](https://htmlpreview.github.io/?https://github.com/STMicroelectronics/stm32f4xx_hal_driver/blob/master/Release_Notes.html). + +## Compatibility information + +It is **crucial** that you use a consistent set of versions for the CMSIS Core - CMSIS Device - HAL, as mentioned in [this](https://htmlpreview.github.io/?https://github.com/STMicroelectronics/STM32CubeF4/blob/master/Release_Notes.html) release note. + +The full **STM32CubeF4** MCU package is available [here](https://github.com/STMicroelectronics/STM32CubeF4). + +## Troubleshooting + +If you have any issue with the **software content** of this repository, you can file an issue [here](https://github.com/STMicroelectronics/stm32f4xx_hal_driver/issues/new/choose). + +For any other question related to the product, the tools, the environment, you can submit a topic on the [ST Community/STM32 MCUs forum](https://community.st.com/s/group/0F90X000000AXsASAW/stm32-mcus). diff --git a/libs/STM32F4xx_HAL_Driver/Release_Notes.html b/libs/STM32F4xx_HAL_Driver/Release_Notes.html new file mode 100644 index 0000000..215114f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Release_Notes.html @@ -0,0 +1,11459 @@ + + + + + + + + Release Notes for STM32F4xx HAL Drivers + +
+
+

 

+
+ + + + + + +
+ + + + + + + + + +
+

Back to + Release page

+
+

Release + + + + Notes for STM32F4xx HAL Drivers

+

Copyright 2017 + STMicroelectronics

+

+
+

 

+ + + + + + +
+ + + + + + + + + +
+

Update + + + + History

V1.8.1 + / 24-June-2022

+
+

Main + + + + + Changes
+

+
+
  • General updates to fix HAL ETH defects and implementation enhancements.
  • HAL + updates

    + + +
      +
    • HAL ETH update
      • Remove useless assert_param(IS_ETH_MAC_ADDRESS0123(MacAddr)) from static function ETH_MACAddressConfig().
      • Replace hard coded Rx buffer size (1000U) by macro ETH_RX_BUF_SIZE.
      • Correct +bit positions when getting MAC and DMA configurations and replace +‘UnicastSlowProtocolPacketDetect’ by ‘UnicastPausePacketDetect’ in the +MAC default configuration structure.
      • Ensure a delay of 4 TX_CLK/RX_CLK cycles between two successive write operations to the same register.
      • Disable DMA transmission in both HAL_ETH_Stop_IT() and HAL_ETH_Stop() APIs.

V1.8.0 + / 11-February-2022

+
+

Main + + + + + Changes
+

+
+
    +
  • General updates to fix known defects and implementation enhancements.
  • +
  • All source files: update disclaimer to add reference to the new license agreement.
    +
  • +
  • The following changes done on the HAL drivers require an update of the application code based on older HAL versions
    • Rework of HAL Ethernet driver to resolve problems and improve performance (compatibility break). 
    • A new HAL Ethernet driver has been redesigned with new APIs, to bypass limitations with previous HAL Ethernet driver version.
    • The new HAL Ethernet driver is the +recommended version. It is located as usual in +Drivers/STM32F4xx_HAL_Driver/Src and Drivers/STM32F4xx_HAL_Driver/Inc +folders. 
      • It can be enabled through switch HAL_ETH_MODULE_ENABLED in stm32f4xx_hal_conf.h
    • The legacy HAL Ethernet driver is also +present in the release in Drivers/STM32F4xx_HAL_Driver/Src/Legacy and +Drivers/STM32F4xx_HAL_Driver/Inc/Legacy folders for software +compatibility reasons.
      • Its usage is not recommended as +deprecated. It can however be enabled through switch +HAL_ETH_LEGACY_MODULE_ENABLED in stm32f4xx_hal_conf.h
    +
  • HAL + updates

    + + +
      + + + + +
    • HAL ETH update +
        +
      • Entire receive process reworked.
      • Resolve the problem of received data corruption.
      • Implement transmission in interrupt mode.
      • Handle one interrupt for multiple transmitted packets.
      • Implement APIs to handle PTP feature.
      • Implement APIs to handle Timestamp feature.
      • Add support of receive buffer unavailable.
      • +
      • Update HAL_ETH_IRQHandler() to handle receive buffer unavailable.
      • + +
    • +
    • HAL SMBUS update
    • +
        +
      • Update to fix issue of mismatched data +received by master in case of data size to be transmitted by the slave +is greater than the data size to be received by the master.
      • +
          +
        • Add flush on TX register.
        • +
        +
      +
    • HAL TIM update
    • +
        +
      • __LL_TIM_CALC_PSC() macro update to round up the evaluate value when the fractional part of the division is greater than 0.5.
      • +
      + +
    • HAL LPTIM update
    • +
        +
      • Add check on PRIMASK register to prevent from enabling unwanted global interrupts within LPTIM_Disable() and LL_LPTIM_Disable()
      • +
      +
    • HAL UART update
    • +
        +
      • Add const qualifier for read only pointers.
      • +
      • Improve header description of UART_WaitOnFlagUntilTimeout() function.
      • +
      • Add a check on the UART parity before enabling the parity error interruption.
      • +
      • Fix typo in UART_IT_TXE bit description.
        +
      • + +
      +
    • HAL IRDA update
    • +
        +
      • Improve header description of IRDA_WaitOnFlagUntilTimeout() function.
      • +
      • Add a check on the IRDA parity before enabling the parity error interrupt.
      • +
      • Add const qualifier for read only pointers.
      • +
      +
    • HAL SMARTCARD update
    • +
        +
      • Improve header description of SMARTCARD_WaitOnFlagUntilTimeout() function
      • +
      • Add const qualifier for read only pointers.
      • +
      +
    • HAL NOR update
    • +
        +
      • Apply adequate commands according to the command set field value
      • +
      • command set 1 for Micron JS28F512P33
      • +
      • command set 2 for Micron M29W128G and Cypress S29GL128P
      • +
      • Add new command operations:
      • +
          +
        • NOR_CMD_READ_ARRAY
        • +
        • NOR_CMD_WORD_PROGRAM
        • +
        • NOR_CMD_BUFFERED_PROGRAM
        • +
        • NOR_CMD_CONFIRM
        • +
        • NOR_CMD_BLOCK_ERASE
        • +
        • NOR_CMD_BLOCK_UNLOCK
        • +
        • NOR_CMD_READ_STATUS_REG
        • +
        • NOR_CMD_CLEAR_STATUS_REG
        • +
        +
      • Update some APIs in order to be compliant for memories with different command set, the updated APIs are:
      • +
          +
        • HAL_NOR_Init()
        • +
        • HAL_NOR_Read_ID()
        • +
        • HAL_NOR_ReturnToReadMode()
        • +
        • HAL_NOR_Read()
        • +
        • HAL_NOR_Program()
        • +
        • HAL_NOR_ReadBuffer()
        • +
        • HAL_NOR_ProgramBuffer()
        • +
        • HAL_NOR_Erase_Block()
        • +
        • HAL_NOR_Erase_Chip()
        • +
        • HAL_NOR_GetStatus()
        • +
        +
      • Align HAL_NOR_Init() API with core of the function when write operation is disabled to avoid HardFault.
      • +
      +
    • HAL SDMMC update
    • +
        +
      • Take into account the voltage range in the CMD1 command.
      • +
      • Add new LL function to have correct response for MMC driver.
      • +
      • Update the driver to have all fields correctly initialized.
      • +
      • Add an internal variable to manage the power class and call it before to update speed of bus width.
      • +
      • Add new API to get the value of the Extended CSD register and populate the ExtCSD field of the MMC handle.
      • +
      • In HAL_MMC_InitCard(), call to SDIO_PowerState_ON() moved after +__HAL_MMC_ENABLE() to ensure MMC clock is enabled before the call to +HAL_Delay() from within SDIO_PowerState_ON().
      • +
      +
    • HAL DMA update
    • +
        +
      • Manage the case of an invalid value of CallbackID passed to the HAL_DMA_RegisterCallback() API.
      • +
      +
    • HAL LTDC update
    • +
        +
      • Update HAL_LTDC_DeInit() to fix MCU Hang up during LCD turn OFF.
      • +
      + +
    • HAL I2C update
    • +
        +
      • Update to fix issue detected due to low system frequency execution (HSI).
      • +
      • Declare an internal macro link to DMA macro to check remaining data: I2C_GET_DMA_REMAIN_DATA
      • +
      • Update HAL I2C Master Receive IT process to safe manage data N= 2 and N= 3.
      • +
          +
        • Disable RxNE interrupt if nothing to do.
        • +
        +
      +
    • HAL USART update
    • +
        +
      • Improve header description of USART_WaitOnFlagUntilTimeout() function.
      • +
      • Add a check on the USART parity before enabling the parity error interrupt.
      • +
      • Add const qualifier for read only pointers.
      • +
      +
    • HAL/LL ADC update
    • +
        +
      • Update LL_ADC_IsActiveFlag_MST_EOCS() API to get the appropriate flag.
      • +
      • Better performance by removing multiple volatile reads or writes in interrupt handler.
      • +
      +
    • HAL FMPI2C update
      +
    • +
        +
      • Update to handle errors in polling mode.
      • +
          +
        • Rename I2C_IsAcknowledgeFailed() to I2C_IsErrorOccurred() and correctly manage when error occurs.
        • +
        +
      +
    • HAL EXTI update
    • +
        +
      • Update HAL_EXTI_GetConfigLine() API to fix wrong calculation of GPIOSel value.
      • +
      +
    • HAL QSPI update
    • +
        +
      • Update HAL_QSPI_Abort() and  +HAL_QSPI_Abort_IT() APIs to check on QSPI BUSY flag status before +executing the abort procedure.
      • +
      + +
    • HAL/LL RTC cleanup
    • +
        +
      • Use bits definitions from CMSIS Device header file instead of hard-coded values.
      • +
      • Wrap comments to be 80-character long and correct typos.
      • +
      • Move constants RTC_IT_TAMP. from hal_rtc.h to hal_rtc_ex.h.
      • +
      • Gather all instructions related to exiting the "init" mode into new function RTC_ExitInitMode().
      • +
      • Add +new macro +assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, +sTamper->Trigger)) to check tamper filtering is disabled in case +tamper events are triggered on signal edges.
      • +
      • Rework functions HAL_RTCEx_SetTamper() and HAL_RTCEx_SetTamper_IT() to:
      • +
          +
        • Write in TAFCR register in one single access instead of two.
        • +
        • Avoid modifying user structure sTamper.
        • +
        +
      • Remove functions LL_RTC_EnablePushPullMode() and LL_RTC_DisablePushPullMode() as related to non-supported features.
      • +
      • Remove any reference to non-supported features (e.g., LL_RTC_ISR_TAMP3F).
      • +
      • Remove +useless conditional defines as corresponding features are supported by +all part-numbers (e.g., #if defined(RTC_TAFCR_TAMPPRCH)).
      • +
      +
    • HAL USB OTG update
    • +
        + + +
      • Fix USB_FlushRxFifo() and USB_FlushTxFifo() APIs by adding check on AHB master IDLE state before flushing the USB FIFO
      • +
      • Fix to avoid resetting host channel direction during channel halt
      • +
      • Fix to report correct received amount of data with USB DMA enabled
      • +
      • Fix to avoid compiler optimization on count variable used for USB HAL timeout loop check
      • +
      • Add missing registered callbacks check for HAL_HCD_HC_NotifyURBChange_Callback()
      • +
      • Add new API HAL_PCD_SetTestMode() APIs to handle USB device high speed Test modes
      • +
      • Setting SNAK for EPs not required during device reset
      • +
      • Update USB IRQ handler to enable EP OUT disable
      • +
      • Add support of USB IN/OUT Iso incomplete
      • +
      • Fix USB BCD data contact timeout
        +
        +
      • + +
      +
    +
  • +
+

V1.7.13 + / 16-July-2021

+
+

Main + + + + + Changes
+

+
+
  • +

    HAL + updates

    + +
      +
    • HAL EXTI + update +
      • Update + HAL_EXTI_GetConfigLine() + API to set default + configuration value of + Trigger and GPIOSel + before checking each + corresponding registers.
      +
    • +
    • HAL GPIO + update +
      • Update + HAL_GPIO_Init() API to + avoid the configuration + of PUPDR register when + Analog mode is selected.
      +
    • +
    • HAL DMA + update +
      • Update + HAL_DMA_IRQHandler() API + to set the DMA state + before unlocking access + to the DMA handle.
      +
    • +
    • HAL/LL ADC + update +
      • Update + LL_ADC_DeInit() API to + clear missing SQR3 + register.
      • Update + LL_ADC_DMA_GetRegAddr() + API to prevent unused + argument compilation + warning.
      • Update HAL + timeout mechanism to + avoid false timeout + detection in case of + preemption.
      +
    • +
    • HAL CAN + update +
      • Update + HAL_CAN_Init() API to be + aligned with referance + manual and to avoid + timeout error:
      +
    • +
    • HAL/LL + RTC_BKP update +
      • Update + __HAL_RTC_…(__HANDLE__, + …) macros to access + registers through + (__HANDLE__)->Instance + pointer and avoid + “unused variable” + warnings.
      • Correct month + management in + IS_LL_RTC_MONTH() macro.
      +
    • +
    • HAL RNG + update +
      • Update timeout + mechanism to avoid false + timeout detection in + case of preemption.
      +
    • +
    • HAL QSPI + update +
      • ES0305 + workaround disabled for + STM32412xx devices.
      +
    • +
    • HAL I2C + update +
      • Update + HAL_I2C_Mem_Write_DMA() + and + HAL_I2C_Mem_Read_DMA() + APIs to initialize + Devaddress, Memaddress + and EventCount + parameters.
      • Update to + prevent several calls of + Start bit: +
        • Update + I2C_MemoryTransmit_TXE_BTF() + API to increment + EventCount.
        +
      • Update to + avoid I2C interrupt in + endless loop: +
        • Update + HAL_I2C_Master_Transmit_IT(), + HAL_I2C_Master_Receive_IT(), + + HAL_I2C_Master_Transmit_DMA() + + and + HAL_I2C_Master_Receive_DMA() + APIs to unlock the + I2C peripheral + before generating + the start.
        +
      • Update to use + the right macro to clear + I2C ADDR flag inside + I2C_Slave_ADDR() API as + it’s indicated in the + reference manual.
      • Update + I2C_IsAcknowledgeFailed() + API to avoid I2C in busy + state if NACK received + after transmitting + register address.
      • Update + HAL_I2C_EV_IRQHandler() + and + I2C_MasterTransmit_BTF() + APIs to correctly manage + memory transfers: +
        • Add check + on memory mode + before calling + callbacks + procedures.
        +
      +
    • +
    • LL USART + update +
      • Handling of + UART concurrent register + access in case of race + condition between Tx and + Rx transfers (HAL UART + and LL LPUART)
      +
    • +
    • HAL SMBUS + update +
      • Updated + HAL_SMBUS_ER_IRQHandler() + API to return the + correct error code + “SMBUS_FLAG_PECERR” in + case of packet error + occurs.
      +
    • +
    • HAL/LL SPI + update +
      • Updated to fix + MISRA-C 2012 Rule-13.2.
      • Update + LL_SPI_TransmitData8() + API to avoid casting the + result to 8 bits.
      +
    • +
    • HAL UART + update +
      • Fix wrong + comment related to RX + pin configuration within + the description section
      • Correction on + UART ReceptionType + management in case of + ReceptionToIdle API are + called from RxEvent + callback
      • Handling of + UART concurrent register + access in case of race + condition between Tx and + Rx transfers (HAL UART + and LL LPUART) +
        • Update CAN + Initialization + sequence to set + "request + initialization" bit + before exit from + sleep mode.
        +
      +
    • +
    • HAL USB + update +
      • HAL PCD: add + fix transfer complete + for IN Interrupt + transaction in single + buffer mode
      • Race condition + in USB PCD control + endpoint receive ISR.
      +
    +

V1.7.12 + / 26-March-2021

+

Main + + + + + Changes

+
    +
  • HAL
  • +
      +
    • HAL/LL + USART update
    • +
        +
      • Fix typo in + USART_Receive_IT() and + USART_TransmitReceive_IT() + APIs to avoid possible + compilation issues if the + UART driver files are not + included.
      • +
      +
    +
+

V1.7.11 + / 12-February-2021

+

Main + + + + + Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Added + + + + new HAL + + + + FMPSMBUS extended driver + + + + + to support FMPSMBUS fast Mode + Plus.
  • +
  • Removed + + + + “register” keyword to be + compliant with new C++ rules:
  • +
      +
    • The register + storage class specifier was + deprecated in C++11 and + removed in C++17.
    • +
    +
  • HAL
  • +
      +
    • HAL update
    • +
    • General + updates to fix known defects + and enhancements + implementation.
    • +
    • Added new + defines for ARM compiler V6:
    • +
        +
      • __weak
      • +
      • __packed
      • +
      • __NOINLINE
      • +
      +
    • Updated HAL TimeBase + TIM, RTC alarm and RTC WakeUp + templates for more robustness
    • +
        +
      • Updated Hal_Init_Tick() + API to propoerty + store the priority when + using the non-default time + base.
      • +
      +
    • Updated + PPP_MODULE_ENABLED for + FMPSMBUS.
    • +
    • HAL/LL ADC update
    • +
        +
      • Updated to + add include of the LL ADC + driver.
      • +
      • Updated the + following APIs to set status + HAL_ADC_STATE_ERROR_INTERNAL + and error code + HAL_ADC_ERROR_INTERNAL when + error occurs:
      • +
          +
        • HAL_ADC_Start()
        • +
        • HAL_ADC_Start_IT()
        • +
        • HAL_ADC_Start_DMA()
        • +
        • HAL_ADCEx_InjectedStart()
        • +
        • HAL_ADCEx_InjectedStart_IT()
        • +
        • HAL_ADCEx_MultiModeStart_DMA()
        • +
        +
      • Updated HAL_ADC_Stop_DMA() + API to check if DMA state is + Busy before calling HAL_DMA_Abort() + + + + + API to avoid DMA internal + error.
      • +
      • Updated + IS_ADC_CHANNEL to support + temperature sensor for:
      • +
          +
        • STM32F411xE
        • +
        • STM32F413xx
        • +
        • STM32F423xx
        • +
        +
      • Fixed wrong + defined values for:
      • +
          +
        • LL_ADC_MULTI_REG_DMA_LIMIT_3
        • +
        • LL_ADC_MULTI_REG_DMA_UNLMT_3
        • +
        +
      • Added + __LL_ADC_CALC_VREFANALOG_VOLTAGE() + macro to evaluate analog + reference voltage.
      • +
      • Removed + __LL_ADC_CALC_TEMPERATURE() + macro for STM32F4x9 devices + as the TS_CAL2 is not + available.
      • +
      +
    • HAL/LL DAC update
    • +
        +
      • Added restruction + on DAC Channel 2 defines and + parametres.
      • +
      • HAL_DAC_MSPINIT_CB_ID + + + + + and HAL_DAC_MSPDEINIT_CB_ID + used instead of + HAL_DAC_MSP_INIT_CB_ID and + HAL_DAC_MSP_DEINIT_CB_ID.
      • +
      • Updated to + support dual mode:
      • +
          +
        • Added two + new APIs:
        • +
            +
          • HAL_DACEx_DualStart()
          • +
          • HAL_DACEx_DualStop()
          • +
          +
        +
      • Added + position bit definition to + be used instead of + __DAC_MASK_SHIFT macro
      • +
          +
        • __DAC_MASK_SHIFT + + + + macro has been removed.
        • +
        +
      • Updated HAL_DAC_Start_DMA() + API to return HAL_ERROR when + error occurs.
      • +
      • Updated HAL_DAC_Stop_DMA() + API to not return HAL_ERROR + when DAC is already + disabled.
      • +
      +
    • HAL CEC update
    • +
        +
      • Updated HAL_CEC_IRQHandler() + API to avoid appending an + extra byte to the end of a + message.
      • +
      +
    • HAL/LL GPIO update
    • +
        +
      • Updated + IS_GPIO_AF() to + add missing values for + STM32F401xC and STM32F401xE + devices:
      • +
          +
        • GPIO_AF3_TIM9
        • +
        • GPIO_AF3_TIM10
        • +
        • GPIO_AF3_TIM11
        • +
        +
      • Updated + LL/HAL GPIO_TogglePin() + APIs to allow multi Pin’s + toggling.
      • +
      • Updated HAL_GPIO_Init() + API to avoid the + configuration of PUPDR + register when Analog mode is + selected.
      • +
      +
    • HAL/LL RCC update
    • +
        +
      • Updated HAL_RCC_OscConfig() + API to add missing checks + and to don’t return + HAL_ERROR if request repeats + the current PLL + configuration.
      • +
      • Updated + IS_RCC_PLLN_VALUE(VALUE) + macro in case of STM32F411xE + device in order to + be aligned with reference + manual.
      • +
      +
    • HAL SD update
    • +
        +
      • Update + function SD_FindSCR() + to resolve issue of FIFO + blocking when reading.
      • +
      • Update + read/write functions in DMA + mode in + + + + order to + force the DMA direction, + updated functions:
      • +
          +
        • HAL_SD_ReadBlocks_DMA()
        • +
        • HAL_SD_WriteBlocks_DMA()
        • +
        +
      • Add the + block size settings in the + initialization functions and + remove it from read/write + transactions to avoid + repeated and inefficient + reconfiguration, updated + functions:
      • +
          +
        • HAL_SD_InitCard()
        • +
        • HAL_SD_GetCardStatus()
        • +
        • HAL_SD_ConfigWideBusOperation(
        • +
        • HAL_SD_ReadBlocks()
        • +
        • HAL_SD_WriteBlocks()
        • +
        • HAL_SD_ReadBlocks_IT()
        • +
        • HAL_SD_WriteBlocks_IT()
        • +
        • HAL_SD_ReadBlocks_DMA()
        • +
        • HAL_SD_WriteBlocks_DMA()
        • +
        +
      +
    • HAL MMC update
    • +
        +
      • Add the + block size settings in the + initialization function and + remove it from read/write + transactions to avoid + repeated and inefficient + reconfiguration, updated + functions:
      • +
          +
        • HAL_MMC_InitCard()
        • +
        • HAL_MMC_ReadBlocks()
        • +
        • HAL_MMC_WriteBlocks()
        • +
        • HAL_MMC_ReadBlocks_IT()
        • +
        • HAL_MMC_WriteBlocks_IT()
        • +
        • HAL_MMC_ReadBlocks_DMA()
        • +
        • HAL_MMC_WriteBlocks_DMA()
        • +
        +
      • Update + read/write functions in DMA + mode in + + + + order to + force the DMA direction, + updated functions:
      • +
          +
        • HAL_MMC_ReadBlocks_DMA()
        • +
        • HAL_MMC_WriteBlocks_DMA()
        • +
        +
      • Deploy new + functions MMC_ReadExtCSD() + and SDMMC_CmdSendEXTCSD + () that read and check the + sectors number of the + device in order to resolve + the issue of wrongly reading + big memory size.
      • +
      +
    • HAL NAND + update
    • +
        +
      • Update + functions + HAL_NAND_Read_SpareArea_16b() + and + HAL_NAND_Write_SpareArea_16b() + to fix column address + calculation issue.
      • +
      +
    • LL SDMMC + update
    • +
        +
      • Update the + definition of + SDMMC_DATATIMEOUT constant in + + + + order to + allow the user to redefine + it in his proper + application.
      • +
      • Remove + 'register' storage class + specifier from LL SDMMC + driver.
      • +
      • Deploy new + functions MMC_ReadExtCSD() + and SDMMC_CmdSendEXTCSD + () that read and check the + sectors number of the device + in order to resolve the + issue of wrongly reading big + memory size.
      • +
      +
    • HAL SMBUS update
    • +
        +
      • Support for + Fast Mode Plus to be SMBUS + rev 3 compliant.
      • +
      • Added HAL_FMPSMBUSEx_EnableFastModePlus() + and HAL_FMPSMBUSEx_DisableFastModePlus() + + + + + APIs to manage Fm+.
      • +
      • Updated SMBUS_MasterTransmit_BTF() + , SMBUS_MasterTransmit_TXE() + + + + + and SMBUS_MasterReceive_BTF() + + + + + APIs to allow stop + generation when CurrentXferOptions + is different from + SMBUS_FIRST_FRAME and + SMBUS_NEXT_FRAME.
      • +
      • Updated SMBUS_ITError() + API to correct the twice + call of HAL_SMBUS_ErrorCallback.
      • +
      +
    • HAL SPI update
    • +
        +
      • Updated HAL_SPI_Init() + API
      • +
          +
        • To avoid + setting the BaudRatePrescaler + in case of Slave Motorola + Mode.
        • +
        • Use the bit-mask + for SPI configuration.
        • +
        +
      • Updated + Transmit/Receive processes + in half-duplex mode
      • +
          +
        • Disable + the SPI instance before + setting BDIOE bit.
        • +
        +
      • Fixed wrong + timeout management
      • +
      • Calculate + Timeout based on a software + loop to avoid blocking issue + if Systick + is disabled.
      • +
      +
    • HAL + SPDIFRX update
    • +
        +
      • Remove + 'register' storage class + specifier from HAL SPDIFRX + driver.
      • +
      +
    • HAL I2S update
    • +
        +
      • Updated + I2SEx APIs to correctly + support circular transfers
      • +
          +
        • Updated + I2SEx_TxRxDMACplt() + API to manage DMA circular + mode.
        • +
        +
      • Updated + HAL_I2SEx_TransmitReceive_DMA() + API to set hdmatx + (transfert + callback and half) to NULL.
      • +
      +
    • HAL SAI update
    • +
        +
      • Updated to + avoid the incorrect + left/right synchronization.
      • +
          +
        • Updated HAL_SAI_Transmit_DMA() + API to follow the sequence + described in the reference + manual for slave + transmitter mode.
        • +
        +
      • Updated HAL_SAI_Init() + API to correct the formula + in case of SPDIF is wrong.
      • +
      +
    • HAL CRYP update
    • +
        +
      • Updated HAL_CRYP_SetConfig() + and HAL_CRYP_GetConfig() + + + + + APIs to set/get the + continent of KeyIVConfigSkip + correctly.
      • +
      +
    • HAL EXTI update
    • +
        +
      • __EXTI_LINE__ + + + + is now used instead of + __LINE__ which is a standard + C macro.
      • +
      +
    • HAL DCMI
    • +
        +
      • Support of + HAL callback registration + feature for DCMI extended + driver.
      • +
      +
    • HAL/LL TIM update
    • +
        +
      • Updated HAL_TIMEx_OnePulseN_Start() + and HAL_TIMEx_OnePulseN_Stop() + + + + + APIs (pooling and IT mode) + to take into consideration + all OutputChannel + parameters.
      • +
      • Corrected + reversed description of + TIM_LL_EC_ONEPULSEMODE One + Pulse Mode.
      • +
      • Updated LL_TIM_GetCounterMode() + API to return the correct + counter mode.
      • +
      +
    • HAL/LL + SMARTCARD update
    • +
        +
      • Fixed + invalid initialization of + SMARTCARD configuration by + removing FIFO mode + configuration as it is not + member of SMARTCARD_InitTypeDef + Structure.
      • +
      • Fixed typos + in SMARTCARD State + definition description
      • +
      +
    • HAL/LL IRDA update
    • +
        +
      • Fixed typos + in IRDA State definition + description
      • +
      +
    • LL USART update
    • +
        +
      • Remove + useless check on maximum BRR + value by removing + IS_LL_USART_BRR_MAX() + macro.
      • +
      • Update + USART polling and + interruption processes to + fix issues related to + accesses out of user + specified buffer.
      • +
      +
    • HAL USB update
    • +
        +
      • Enhanced + USB OTG host HAL with USB + DMA is enabled:
      • +
          +
        • fixed + ping and data toggle + issue,
        • +
        • reworked + Channel error report + management
        • +
        +
      +
    +
+

V1.7.10 + + + + / 22-October-2020

+

Main Changes

+
    +
  • General + + + + updates to fix known defects.
  • +
  • HAL/LL + + + + I2C update
  • +
+
    +
      +
    •   Update + to fix hardfault + issue with HAL_I2C_Mem_Write_DMA() + API:
    • +
        +
      •   + Abort the right ongoing DMA + transfer when memory write + access request operation + failed: fix typo “hdmarx” + replaced by “hdmatx”
      • +
      +
    +
+

V1.7.9 + + + + / 14-August-2020

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL/LL + + + + I2C update
  • +
+
    +
      +
    •   Update + HAL_I2C_ER_IRQHandler() + API to fix acknowledge failure + issue with I2C memory IT + processes
    • +
        +
      •   Add + stop condition generation + when NACK occurs.
      • +
      +
    •   Update + I2C_DMAXferCplt(), + + + + + I2C_DMAError() and + I2C_DMAAbort() APIs to fix hardfault + issue when hdmatx + and hdmarx + parameters in i2c handle + aren't initialized (NULL + pointer).
    • +
        +
      •   Add + additional check on + hi2c->hdmtx + and hi2c->hdmarx + before resetting DMA Tx/Rx + complete callbacks
      • +
      +
    •   Update + Sequential transfer APIs to + adjust xfermode + condition.
    • +
        +
      •   + + + + + Replace hi2c->XferCount + < MAX_NBYTE_SIZE by + hi2c->XferCount + <= MAX_NBYTE_SIZE which + corresponds to a case + without reload
      • +
      +
    +
+
    +
  •  HAL/LL + + + + USB update
  • +
      +
    •   Bug + + + + fix: USB_ReadPMA() + and USB_WritePMA() + + + + + by ensuring 16-bits access to + USB PMA memory
    • +
    •   Bug + + + + fix: correct USB RX count + calculation
    • +
    •   Fix + USB Bulk transfer double + buffer mode
    • +
    •   Remove + register keyword from USB + defined macros as no more + supported by C++ compiler
    • +
    •   Minor + rework on USBD_Start() + and USBD_Stop() + + + + + APIs: stopping device will be + handled by HAL_PCD_DeInit() + + + + + API.
    • +
    •   Remove + non used API for USB device + mode.
    • +
    +
+

V1.7.8 + + + + / 12-February-2020

+

Main Changes

+
    +
  • Add + new HAL FMPSMBUS and LL + + + + FMPI2C drivers
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
+
    +
  • Update + + + + HAL CRYP driver to support block + by block decryption without + reinitializes the IV and KEY for + each call.
  • +
  • Improve + + + + code quality by fixing + MisraC-2012 violations
  • +
  • HAL/LL + + + + USB update
  • +
      +
    •  Add + handling USB host babble error + interrupt
    • +
    •  Fix + Enabling ULPI interface for + platforms that integrates USB + HS PHY
    • +
    •  Fix + Host data toggling for IN Iso + transfers
    • +
    •  Ensure + to disable USB EP during + endpoint deactivation
    • +
    +
  • HAL + + + + CRYP update
  • +
      +
    •  Update + HAL CRYP driver to support + block by block decryption + without initializing the IV + and KEY at each call.
    • +
        +
      • Add new + CRYP Handler parameters: "KeyIVConfig" + and "SizesSum"
      • +
      • Add new + CRYP init + parameter: "KeyIVConfigSkip"
      • +
      +
    +
  • HAL + + + + I2S update
  • +
      +
    • Update + HAL_I2S_DMAStop() + API to be more safe
    • +
        +
      • Add a check + on BSY, TXE and RXNE flags + before disabling the I2S
      • +
      +
    • Update + HAL_I2S_DMAStop() + API to fix multi-call transfer + issue(to avoid re-initializing + the I2S for the next + transfer).
    • +
        +
      • Add + __HAL_I2SEXT_FLUSH_RX_DR() + and __HAL_I2S_FLUSH_RX_DR() + macros to flush the + remaining data inside DR + registers.
      • +
      • Add new ErrorCode + define: + HAL_I2S_ERROR_BUSY_LINE_RX
      • +
      +
    +
+

V1.7.7 + + + + / 06-December-2019

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL + + + + Generic update
  • +
      +
    • HAL_SetTickFreq(): update to + restore the previous tick + frequency when HAL_InitTick() + + + + + configuration failed.
    • +
    +
  • HAL/LL + + + + GPIO update
  • +
      +
    • Update GPIO + initialization sequence to + + + + avoid unwanted pulse on GPIO Pin's
    • +
    +
  • HAL + + + + EXTI update
  • +
+
    +
      +
    • General + update to enhance HAL EXTI + driver robustness 
    • +
        +
      • Add + additional assert check on + EXTI config lines
      • +
      • Update to + compute EXTI line mask + before read/write access + to EXTI registers
        +
        +
      • +
      +
    • Update EXTI + callbacks management to be + compliant with reference + manual: only one PR + register for rising and + falling interrupts.
    • +
        +
      • Update + parameters in EXTI_HandleTypeDef + structure: merge HAL + EXTI RisingCallback + and FallingCallback + in only one PendingCallback
      • +
      • Remove + HAL_EXTI_RISING_CB_ID and + HAL_EXTI_FALLING_CB_ID + values from EXTI_CallbackIDTypeDef + enumeration.
        +
        +
      • +
      +
    • Update + HAL_EXTI_IRQHandler() + API to serve interrupts + correctly.
    • +
        +
      • Update to + compute EXTI line mask + before handle + EXTI interrupt.
      • +
      +
    • Update to + support GPIO port + interrupts:
    • +
        +
      • Add new "GPIOSel" + parameter in EXTI_ConfigTypeDef + structure
      • +
      +
    +
  • HAL/LL + + + + RCC update
  • +
      +
    • Update HAL_RCCEx_PeriphCLKConfig() + API to support PLLI2S + configuration for STM32F42xxx + and STM32F43xxx devices
    • +
    • Update the HAL_RCC_ClockConfig() + and HAL_RCC_DeInit() + + + + + API to don't overwrite the + custom tick priority
    • +
    • Fix LL_RCC_DeInit() + failure detected with gcc + compiler and high optimization + level is selected(-03)
    • +
    • Update HAL_RCC_OscConfig() + API to don't return + HAL_ERROR if request repeats + the current PLL configuration
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • Update LL_ADC_REG_Init() + to fix wrong ADC CR1 register + configuration
    • +
        +
      • The ADC + sequencer length is part + of ADC SQR1 + register not of ADC CR1 + register
      • +
      +
    +
  • HAL + + + + CRYP update
  • +
      +
    • Update HAL_CRYP_Encrypt() + and HAL_CRYP_Decrypt() + + + + + APIs to take into + consideration the datatype fed + to the DIN register (1-, 8-, + 16-, or 32-bit data) when + padding the last block of the + payload, in case the size of + this last block is less than + 128 bits.
    • +
    +
  • HAL + + + + RNG update
  • +
      +
    • Update HAL_RNG_IRQHandler() + API to fix error code + management issue: error code + is assigned + "HAL_RNG_ERROR_CLOCK" in case + of clock error and + "HAL_RNG_ERROR_SEED" in case + of seed error, not the + opposite.
    • +
    +
  • HAL + + + + DFSDM update
  • +
      +
    • Update DFSDM_GetChannelFromInstance() + API to remove unreachable + check condition
    • +
    +
  • HAL + + + + DMA update
  • +
      +
    • Update HAL_DMA_Start_IT() + API to omit the FIFO error
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • Update FLASH_Program_DoubleWord() + API to fix with EWARM high + level optimization issue
    • +
    +
  • HAL + + + + QSPI update
  • +
      +
    • Remove Lock + mechanism from HAL_QSPI_Init() + and HAL_QSPI_DeInit() + + + + + APIs
    • +
    +
  • HAL + + + + HASH update
  • +
      +
    • Null pointer + on handler "hhash" + is now checked before + accessing structure member "hhash->Init.DataType" + in the following API:
    • +
        +
      • HAL_HASH_Init()
      • +
      +
    • Following interrupt-based + APIs have been added. + Interrupt mode could allow the + MCU to enter "Sleep" mode + while a data block is being + processed. Please refer to the + "##### How to use this driver + #####" section for details + about their use.
    • +
        +
      • HAL_HASH_SHA1_Accmlt_IT()
      • +
      • HAL_HASH_MD5_Accmlt_IT()
      • +
      • HAL_HASHEx_SHA224_Accmlt_IT()
      • +
      • HAL_HASHEx_SHA256_Accmlt_IT()
      • +
      +
    • Following aliases + have been added (just for + clarity sake) as they + shall be used at the end + of the computation of a + multi-buffers message and not + at the start:
    • +
        +
      • HAL_HASH_SHA1_Accmlt_End() + to be used instead of + HAL_HASH_SHA1_Start()
      • +
      • HAL_HASH_MD5_Accmlt_End() + to be used instead of + HAL_HASH_MD5_Start()
      • +
      • HAL_HASH_SHA1_Accmlt_End_IT() + to be used instead of + HAL_HASH_SHA1_Start_IT()
      • +
      • HAL_HASH_MD5_Accmlt_End_IT() + to be used instead of + HAL_HASH_MD5_Start_IT()
      • +
      • HAL_HASHEx_SHA224_Accmlt_End() + to be used instead of + HAL_HASHEx_SHA224_Start()
      • +
      • HAL_HASHEx_SHA256_Accmlt_End() + to be used instead of + HAL_HASHEx_SHA256_Start()
      • +
      +
    +
+
    +
      +
        +
      • HAL_HASHEx_SHA224_Accmlt_End_IT() + to be used instead of + HAL_HASHEx_SHA224_Start_IT()
      • +
      • HAL_HASHEx_SHA256_Accmlt_End_IT() + to be used instead of + HAL_HASHEx_SHA256_Start_IT()
      • +
      +
    +
+
    +
      +
    • MISRAC-2012 + rule R.5.1 (identifiers + shall be distinct in the first + 31 characters) constrained the + naming of the above listed + aliases (e.g. + HAL_HASHEx_SHA256_Accmlt_End() + could not be named + HAL_HASHEx_SHA256_Accumulate_End(). + + + + + Otherwise the name would have + conflicted with + HAL_HASHEx_SHA256_Accumulate_End_IT()). + In + + + + + order to + have aligned names following + APIs have been renamed:
    • +
    +
+
    +
      +
        +
          +
        • HAL_HASH_MD5_Accumulate() + renamed + HAL_HASH_MD5_Accmlt()
        • +
        • HAL_HASH_SHA1_Accumulate() + renamed + HAL_HASH_SHA1_Accmlt()
        • +
        • HAL_HASHEx_SHA224_Accumulate() + renamed + HAL_HASHEx_SHA224_Accmlt()
        • +
        +
      +
    +
+
    +
      +
        +
          +
        • HAL_HASHEx_SHA256_Accumulate() + renamed + HAL_HASHEx_SHA256_Accmlt()
        • +
        +
      +
    +
+
    +
      +
    • HASH handler + state is no more + reset to HAL_HASH_STATE_READY + once DMA has been started + in the following APIs:
    • +
        +
      • HAL_HASH_MD5_Start_DMA()
      • +
      • HAL_HMAC_MD5_Start_DMA()
      • +
      • HAL_HASH_SHA1_Start_DMA()
      • +
      • HAL_HMAC_SHA1_Start_DMA()
      • +
      +
    • HASH phase + state is now set to + HAL_HASH_PHASE_READY once + the digest has been read + in the following APIs:
    • +
        +
      • HASH_IT()
      • +
      • HMAC_Processing()
      • +
      • HASH_Start()
      • +
      • HASH_Finish()
      • +
      +
    • Case of a + large buffer scattered around + in memory each piece of which + is not necessarily a multiple + + + + of 4 bytes in length.
    • +
        +
      • In section + "##### How to use this + driver #####", sub-section + "*** Remarks on message + length ***" added to provide + recommendations to follow in + such case.
      • +
      • No + modification of the driver + as the root-cause is at + design-level.
      • +
      +
    +
+
    +
  • HAL CAN + + + + update
  • +
      +
    • HAL_CAN_GetRxMessage() update to + get the correct value for the + RTR (type of frame for + the message that will be + transmitted) field in the CAN_RxHeaderTypeDef + structure.
    • +
    +
  • HAL + + + + DCMI update
  • +
      +
    • Add new HAL_DCMI_ConfigSyncUnmask() + API to set embedded + synchronization delimiters + unmasks.
    • +
    +
  • HAL + + + + RTC update
  • +
      +
    • Following IRQ + handlers' implementation has + been aligned with the + STM32Cube firmware + specification (in case of + interrupt lines shared by + multiple events, first check + the IT enable bit is set then + check the IT flag is set too):
    • +
        +
      • HAL_RTC_AlarmIRQHandler()
      • +
      • HAL_RTCEx_WakeUpTimerIRQHandler()
      • +
      • HAL_RTCEx_TamperTimeStampIRQHandler()
      • +
      +
    +
+
    +
  • HAL + + + + WWDG update
  • +
      +
    • In "##### + WWDG Specific features #####" + descriptive comment section:
    • +
        +
      • Maximal prescaler + value has been corrected (8 + instead of 128).
      • +
      • Maximal APB + frequency has been corrected + (42MHz instead of 56MHz) and + possible timeout values + updated.
      • +
      +
    +
  • HAL + + + + DMA2D update
  • +
+
    +
      +
    • Add the + following API's to Start DMA2D + CLUT Loading.
    • +
        +
      • HAL_DMA2D_CLUTStartLoad() + Start DMA2D CLUT Loading.
      • +
      • HAL_DMA2D_CLUTStartLoad_IT() + Start DMA2D CLUT Loading + with interrupt enabled.
      • +
      +
    • The following + old wrong services will be + kept in the HAL DCMI driver + for legacy purpose and a + specific Note is added:
    • +
        +
      • HAL_DMA2D_CLUTLoad() + can be replaced with + HAL_DMA2D_CLUTStartLoad()
      • +
      • HAL_DMA2D_CLUTLoad_IT() can + + + + + be replaced with + HAL_DMA2D_CLUTStartLoad_IT()
      • +
      • HAL_DMA2D_ConfigCLUT() + can be omitted as the config + can be performed using + the HAL_DMA2D_CLUTStartLoad() + API.
      • +
      +
    +
+
    +
  • HAL + + + + SDMMC update
  • +
      +
    • Fix  + typo in "FileFormatGroup" + parameter in the HAL_MMC_CardCSDTypeDef + and HAL_SD_CardCSDTypeDef + structures 
    • +
    • Fix an + improve handle state and + error management
    • +
    • Rename the + defined MMC card capacity type + to be more meaningful:
    • +
        +
      • Update MMC_HIGH_VOLTAGE_CARD to + + + + + MMC LOW_CAPACITY_CARD
      • +
      • Update MMC_DUAL_VOLTAGE_CRAD + to MMC_HIGH_CAPACITY_CARD
      • +
      +
    • Fix + management of peripheral + flags depending on commands + or data transfers
    • +
        +
      • Add new + defines + "SDIO_STATIC_CMD_FLAGS" + and "SDIO_STATIC_DATA_FLAGS" 
      • +
      • Updates HAL + + + + SD and HAL MMC drivers to + manage the new SDIO static + flags.
        +
        +
      • +
      +
    • Due to + limitation SDIO hardware flow + control indicated in Errata + Sheet:
    • +
        +
      • In 4-bits + bus wide mode, do not use + the HAL_SD_WriteBlocks_IT() + or HAL_SD_WriteBlocks() + + + + + APIs otherwise underrun will + occur and it isn't possible + to activate the flow + control.
      • +
      • Use DMA + mode when using 4-bits bus + wide mode or decrease the + SDIO_CK frequency.
      • +
      +
    +
  • HAL + + + + UART update
  • +
      +
    • Update UART + polling processes to handle + efficiently the Lock mechanism
    • +
        +
      •  Move + the process unlock at the + top of the HAL_UART_Receive() + and HAL_UART_Transmit() + + + + + API.
      • +
      +
    • Fix baudrate + calculation error for clock + higher than 172Mhz
    • +
        +
      • Add a + forced cast on + UART_DIV_SAMPLING8() and + UART_DIV_SAMPLING16() + macros.
      • +
      • Remove + useless parenthesis from + UART_DIVFRAQ_SAMPLING8(), + UART_DIVFRAQ_SAMPLING16(), + UART_BRR_SAMPLING8() and + UART_BRR_SAMPLING16() macros + to solve some MISRA + warnings.
      • +
      +
    • Update UART + interruption handler to manage + correctly the overrun interrupt
    • +
        +
      • Add in + the HAL_UART_IRQHandler() + API a check on + USART_CR1_RXNEIE bit when an + overrun interrupt occurs.
      • +
      +
    • Fix baudrate + calculation error UART9 + and UART10
    • +
        +
      • In UART_SetConfig() + API fix UART9 and UART10 + clock source when computing + baudrate + values by adding a check on + these instances and setting + clock sourcePCLK2 instead of + PCLK1.
      • +
      +
    • Update UART_SetConfig() + API
    • +
        +
      • Split + HAL_RCC_GetPCLK1Freq() + and HAL_RCC_GetPCLK2Freq() + macros from the + UART_BRR_SAMPLING8() and + UART_BRR_SAMPLING8() + macros 
      • +
      +
    +
  • HAL + + + + USART update
  • +
      +
    • Fix baudrate + calculation error for clock + higher than 172Mhz
    • +
        +
      • Add a + forced cast on USART_DIV() + macro.
      • +
      • Remove + useless parenthesis + from USART_DIVFRAQ() + macro to solve some MISRA + warnings.
      • +
      +
    • Update USART + interruption handler to manage + correctly the overrun interrupt
    • +
        +
      • Add in + the HAL_USART_IRQHandler() + API a check on + USART_CR1_RXNEIE bit when an + overrun interrupt occurs.
      • +
      +
    • Fix baudrate + calculation error UART9 + and UART10
    • +
        +
      • In USART_SetConfig() + API fix UART9 and UART10 + clock source when computing + baudrate + values by adding a check on + these instances and setting + clock sourcePCLK2 instead of + PCLK1.
      • +
      +
    • Update USART_SetConfig() + API
    • +
        +
      • Split + HAL_RCC_GetPCLK1Freq() + and HAL_RCC_GetPCLK2Freq() + macros from the USART_BRR() + macro
      • +
      +
    +
  • HAL + + + + IRDA update
  • +
      +
    • Fix baudrate + calculation error for clock + higher than 172Mhz
    • +
        +
      • Add a + forced cast on IRDA_DIV() + macro.
      • +
      • Remove + useless parenthesis + from IRDA_DIVFRAQ() + macro to solve some + MISRA warnings.
      • +
      +
    • Update IRDA + interruption handler to manage + correctly the overrun interrupt
    • +
        +
      • Add in + the HAL_IRDA_IRQHandler() + API a check on + USART_CR1_RXNEIE bit when an + overrun interrupt occurs.
      • +
      +
    • Fix baudrate + calculation error UART9 + and UART10
    • +
        +
      • In IRDA_SetConfig() + API fix UART9 and UART10 + clock source when computing + baudrate + values by adding a check on + these instances and setting + clock sourcePCLK2 instead of + PCLK1.
      • +
      +
    • Update IRDA_SetConfig() + API
    • +
        +
      • Split + HAL_RCC_GetPCLK1Freq() + and HAL_RCC_GetPCLK2Freq() + macros from the IRDA_BRR() + macro
      • +
      +
    +
  • HAL + + + + SMARTCARD update
  • +
      +
    • Fix baudrate + calculation error for clock + higher than 172Mhz
    • +
        +
      • Add a + forced cast on SMARTCARD_DIV() + macro.
      • +
      • Remove useless parenthesis + + + + + from SMARTCARD_DIVFRAQ() + macro to solve some + MISRA warnings.
      • +
      +
    • Update + SMARTCARD interruption handler + to manage correctly the + overrun interrupti
    • +
        +
      • Add in + the HAL_SMARTCARD_IRQHandler() + API a check on + USART_CR1_RXNEIE bit when an + overrun interrupt occurs.
      • +
      +
    • Update SMARTCARD_SetConfig() + API
    • +
        +
      • Split + HAL_RCC_GetPCLK1Freq() + and HAL_RCC_GetPCLK2Freq() + macros from the + SMARTCARD_BRR() macro
      • +
      +
    +
  • HAL + + + + TIM update
  • +
      +
    • Add new + macros to enable and disable + the fast mode when using the + one pulse mode to output a + waveform with a minimum delay
    • +
        +
      • __HAL_TIM_ENABLE_OCxFAST() + and __HAL_TIM_DISABLE_OCxFAST().
      • +
      +
    • Update + Encoder interface mode to + keep TIM_CCER_CCxNP + bits low
    • +
        +
      • Add TIM_ENCODERINPUTPOLARITY_RISING + + + + + and + TIM_ENCODERINPUTPOLARITY_FALLING + definitions to determine + encoder input polarity.
      • +
      • Add + IS_TIM_ENCODERINPUT_POLARITY() + macro to check the + encoder input polarity.
      • +
      • Update HAL_TIM_Encoder_Init() + API 
      • +
          +
        • Replace + IS_TIM_IC_POLARITY() + macro by + IS_TIM_ENCODERINPUT_POLARITY() + macro.
        • +
        +
      +
    • Update TIM + remapping input configuration + in HAL_TIMEx_RemapConfig() + API
    • +
        +
      • Remove + redundant check on + LPTIM_OR_TIM5_ITR1_RMP bit + and replace it by check on + LPTIM_OR_TIM9_ITR1_RMP bit.
      • +
      +
    • Update HAL_TIMEx_MasterConfigSynchronization() + API to avoid functional errors + and assert fails when using + some TIM instances as input + trigger.
    • +
        +
      • Replace IS_TIM_SYNCHRO_INSTANCE() + macro by + IS_TIM_MASTER_INSTANCE() + macro. 
      • +
      • Add IS_TIM_SLAVE_INSTANCE() + macro to check on + TIM_SMCR_MSM bit.
      • +
      +
    • Add lacking + TIM input remapping definition 
    • +
        +
      • Add + LL_TIM_TIM11_TI1_RMP_SPDIFRX + and + LL_TIM_TIM2_ITR1_RMP_ETH_PTP.
      • +
      • Add lacking + definition for linked + LPTIM_TIM input trigger remapping  
      • +
          +
        • Add + following definitions + + + + + : + LL_TIM_TIM9_ITR1_RMP_TIM3_TRGO, + LL_TIM_TIM9_ITR1_RMP_LPTIM, + + + + LL_TIM_TIM5_ITR1_RMP_TIM3_TRGO, + + + + + LL_TIM_TIM5_ITR1_RMP_LPTIM, + + + + LL_TIM_TIM1_ITR2_RMP_TIM3_TRGO + + + + and + LL_TIM_TIM1_ITR2_RMP_LPTIM.
        • +
        • Add a new + mechanism in LL_TIM_SetRemap() + API to remap TIM1, TIM9, + and TIM5 input + triggers mapped on LPTIM + register. 
        • +
        +
      +
    +
  • HAL + + + + LPTIM update
  • +
      +
    • Add a polling + mechanism to check + on LPTIM_FLAG_XXOK flags + in different API 
    • +
        +
      • Add  + LPTIM_WaitForFlag() API to + wait for flag set.
      • +
      • Perform new + checks on + HAL_LPTIM_STATE_TIMEOUT.
      • +
      +
    • Add lacking + definitions of LPTIM input + trigger remapping and its + related API
    • +
        +
          +
        • LL_LPTIM_INPUT1_SRC_PAD_AF, + + + + + LL_LPTIM_INPUT1_SRC_PAD_PA4, + + + + LL_LPTIM_INPUT1_SRC_PAD_PB9 + + + + and + LL_LPTIM_INPUT1_SRC_TIM_DAC.
        • +
        • Add a new + API LL_LPTIM_SetInput1Src() + to access to the LPTIM_OR + register and remap the + LPTIM input trigger.
        • +
        +
      +
    • Perform a new + check on indirect EXTI23 line + associated to the LPTIM wake + up timer
    • +
        +
      • Condition + the use of the LPTIM Wake-up + Timer associated EXTI + line configuration's + macros by EXTI_IMR_MR23 + bit in different API + + + + :
      • +
          +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE/DDISABLE_FALLING_EDGE()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_FALLING_EDGE()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_FALLING_EDGE()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_FALLING_EDGE()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_GET_FLAG()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG()
        • +
        • __HAL_LPTIM_WAKEUPTIMER_EXTI_GENERATE_SWIT(
        • +
        +
      • Update HAL_LPTIM_TimeOut_Start_IT(), HAL_LPTIM_TimeOut_Stop_IT(), + + + + + HAL_LPTIM_Counter_Start_IT() + + + + + and HAL_LPTIM_Counter_Stop_IT() + + + + + API by adding Enable/Disable + rising edge trigger on + the LPTIM Wake-up Timer + Exti + line.
      • +
      • Add + __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG() + in the end of the HAL_LPTIM_IRQHandler() + + + + + API conditioned by + EXTI_IMR_MR23 bit.
      • +
      +
    +
  • HAL + + + + I2C update
  • +
      +
    • Update + HAL_I2C_EV_IRQHandler() + API to fix I2C send break + issue 
    • +
        +
      • Add + additional check on + hi2c->hdmatx, + hdmatx->XferCpltCallback, + hi2c->hdmarx, + hdmarx->XferCpltCallback + in I2C_Master_SB() + API to avoid enabling + DMA request when IT + mode is used.
      • +
      +
    • Update + HAL_I2C_ER_IRQHandler() + API to fix acknowledge failure + issue with I2C memory IT + processes
    • +
        +
      •  Add stop + + + + + condition generation when + NACK occurs.
      • +
      +
    • Update + HAL_I2C_Init() + API to force software reset + before setting new I2C + configuration
    • +
    • Update HAL + I2C processes to report ErrorCode + when wrong I2C start condition + occurs
    • +
        +
      •  Add + new ErrorCode + define: HAL_I2C_WRONG_START
      • +
      •  Set ErrorCode + parameter in I2C handle + to HAL_I2C_WRONG_START
      • +
      +
    • Update I2C_DMAXferCplt(), + + + + + I2C_DMAError() and + I2C_DMAAbort() APIs to fix hardfault + issue when hdmatx + and hdmarx parameters + + + + + in i2c handle aren't + initialized (NULL pointer).
    • +
        +
      • Add + additional check on + hi2c->hdmtx + and hi2c->hdmarx + before resetting DMA + Tx/Rx complete callbacks
      • +
      +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Fix HAL + FMPI2C slave interrupt + handling issue with I2C + sequential transfers.
    • +
        +
      • Update + FMPI2C_Slave_ISR_IT() + and FMPI2C_Slave_ISR_DMA() + APIs to check on STOP + condition and handle it + before clearing the ADDR + flag
      • +
      +
    +
  • HAL + + + + NAND update
  • +
      +
    • Update + HAL_NAND_Write_Page_8b(), + + + + HAL_NAND_Write_Page_16b() + and  + HAL_NAND_Write_SpareArea_16b() + to manage correctly the time + out condition.
    • +
    +
  • HAL + + + + SAI update
  • +
      +
    • Optimize SAI_DMATxCplt() + and SAI_DMARxCplt() + + + + + APIs to check on "Mode" + parameter instead of CIRC + bit in the CR register.
    • +
    • Remove unused + SAI_FIFO_SIZE define
    • +
    • Update HAL_SAI_Receive_DMA() + programming sequence to be inline + with reference manual
    • +
    +
+

V1.7.6 + + + + / 12-April-2019

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL + + + + I2C update
  • +
      +
    • Fix I2C send + break issue in IT processes
    • +
        +
      • Add + additional check on + hi2c->hdmatx + and hi2c->hdmarx to + + + + + avoid the DMA request + enable when IT mode is used.
      • +
      +
    +
  • HAL + + + + SPI update
  • +
      +
    • Update to + implement Erratasheet: + BSY bit may stay high at the + end of a data transfer in + Slave mode
    • +
    +
  • LL + + + + LPTIM update
  • +
      +
    • Fix + compilation errors with LL_LPTIM_WriteReg() + and LL_LPTIM_ReadReg() + + + + + macros
    • +
    +
  • HAL + + + + SDMMC update
  • +
      +
    • Fix + preprocessing compilation + issue with SDIO + STA STBITERR interrupt
    • +
    +
  • HAL/LL + + + + USB update
  • +
      +
    • Updated USB_WritePacket(), + + + + + USB_ReadPacket() + + + + + APIs to prevent compilation + warning with GCC GNU v8.2.0
    • +
    • Rework USB_EPStartXfer() + API to enable the USB endpoint + before unmasking the TX FiFo + empty interrupt in case DMA is + not used
    • +
    • USB HAL_HCD_Init() + and HAL_PCD_Init() + + + + + APIs updated to avoid enabling + USB DMA feature for OTG FS + instance, USB DMA feature is + available only on OTG HS + Instance
    • +
    • Remove + duplicated line in hal_hcd.c + header file comment section +
    • +
    • Rework USB + HAL driver to use instance PCD_SPEED_xxx, + HCD_SPEED_xx + speeds instead of OTG register + Core speed definition during + the instance initialization
    • +
    • Software + Quality improvement with a fix + of CodeSonar + warning on PCD_Port_IRQHandler() + and  HCD_Port_IRQHandler() + + + + + interrupt handlers
    • +
    +
+

V1.7.5 + + + + / 08-February-2019

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • General + + + + updates to fix CodeSonar + compilation warnings
  • +
  • General + + + + updates to fix SW4STM32 + compilation errors under Linux
  • +
  • General + + + + updates to fix the user manual + .chm files
  • +
  • Add + support of HAL callback + registration feature
  • +
+
    +
  • Add + new HAL + + + + EXTI driver
  • +
  • Add + new HAL + + + + SMBUS driver
  • +
  • The + + + + following changes done on the + HAL drivers require an update + on the application code based + on older HAL versions
  • +
      +
    • Rework of HAL + CRYP driver (compatibility + break)
    • +
        +
      • HAL CRYP + driver has been redesigned + with new API's, to bypass + limitations on data + Encryption/Decryption + management present with + previous HAL CRYP driver + version.
      • +
      • The new HAL + CRYP driver is the + recommended version. It is + located as usual in + Drivers/STM32F4xx_HAL_Driver/Src + and + Drivers/STM32f4xx_HAL_Driver/Inc + folders. It can be enabled + through switch + HAL_CRYP_MODULE_ENABLED in + stm32f4xx_hal_conf.h
      • +
      • The legacy + HAL CRYP driver is no longer + supported.
      • +
      +
    • Add new AutoReloadPreload + field in TIM_Base_InitTypeDef + structure to allow the + possibilities to enable or + disable the TIM Auto Reload + Preload.
    • +
    +
+
    +
  • HAL/LL + + + + Generic update
  • +
      +
    • Add support + of HAL callback + registration feature
    • +
        +
      • The feature + disabled by default is + available for the following + HAL drivers:
      • +
          +
        • ADC, + CAN, CEC, CRYP, DAC, + DCMI, DFSDM, DMA2D, DSI, + ETH, HASH, HCD, I2C, + FMPI2C, SMBUS,
          + UART, USART, IRDA, + SMARTCARD, LPTIM, LTDC, + MMC, NAND, NOR, + PCCARD, PCD, QSPI, RNG,

          +
          RTC, + SAI, SD, SDRAM, SRAM, + SPDIFRX, SPI, I2S, TIM, + and WWDG
        • +
        +
      • The feature + may be enabled individually + per HAL PPP driver + by setting the corresponding + definition USE_HAL_PPP_REGISTER_CALLBACKS + + + + + to 1U in + stm32f4xx_hal_conf.h project + configuration file (template + file + stm32f4xx_hal_conf_template.h + available from  + + + + Drivers/STM32F4xx_HAL_Driver/Inc)
      • +
      • Once enabled + + + + , the user + application may resort to HAL_PPP_RegisterCallback() + + + + + to register specific + callback function(s) and + unregister it(them) with HAL_PPP_UnRegisterCallback().
      • +
      +
    • General + updates to fix MISRA 2012 + compilation errors
    • +
        +
      • Replace HAL_GetUID() + API by HAL_GetUIDw0(), + HAL_GetUIDw1() and + HAL_GetUIDw2()
      • +
      • HAL_IS_BIT_SET()/HAL_IS_BIT_CLR() + macros implementation update
      • +
      • "stdio.h" + include updated with "stddef.h"
      • +
      +
    +
  • HAL + + + + GPIO  + + + + update
  • +
      +
    • Add missing + define for SPI3 alternate + function "GPIO_AF5_SPI3" for + STM32F401VE devices
    • +
    • Remove + "GPIO_AF9_TIM14" from defined + alternate function list for + STM32F401xx devices
    • +
    • HAL_GPIO_TogglePin() reentrancy + robustness improvement
    • +
    • HAL_GPIO_DeInit() API update + to avoid potential pending + interrupt after call
    • +
    • Update + GPIO_GET_INDEX() + API for more compliance with + STM32F412Vx/STM32F412Rx/STM32F412Cx + devices
    • +
    • Update + GPIO_BRR registers with + Reference Manual regarding + registers and bit definition + values
    • +
    +
  • HAL + + + + CRYP update
  • +
      +
    • The CRYP_InitTypeDef + is no more + supported, changed by CRYP_ConfigTypedef + to allow changing parameters + using HAL_CRYP_setConfig() + API without reinitialize the + CRYP IP using the HAL_CRYP_Init() + + + + + API
    • +
    • New + parameters added in the CRYP_ConfigTypeDef + structure: B0 and DataWidthUnit
    • +
    • Input data + size parameter is added in the + CRYP_HandleTypeDef + structure
    • +
    • Add new APIs + to manage the CRYP + configuration:
    • +
        +
      •  HAL_CRYP_SetConfig()
      • +
      • HAL_CRYP_GetConfig()
      • +
      +
    • Add new APIs + to manage the Key derivation:
    • +
        +
      • HAL_CRYPEx_EnableAutoKeyDerivation()
      • +
      • HAL_CRYPEx_DisableAutoKeyDerivation()
      • +
      +
    • Add new APIs + to encrypt and decrypt data:
    • +
        +
      • HAL_CRYP_Encypt()
      • +
      • HAL_CRYP_Decypt()
      • +
      • HAL_CRYP_Encypt_IT()
      • +
      • HAL_CRYP_Decypt_IT()
      • +
      • HAL_CRYP_Encypt_DMA()
      • +
      • HAL_CRYP_Decypt_DMA()
      • +
      +
    • Add new APIs + to generate TAG:
    • +
        +
      • HAL_CRYPEx_AESGCM_GenerateAuthTAG()
      • +
      • HAL_CRYPEx_AESCCM_Generago teAuthTAG()
      • +
      +
    +
  • HAL + + + + LPTIM update
  • +
      +
    • Remove + useless LPTIM Wakeup EXTI + related macros from HAL_LPTIM_TimeOut_Start_IT() + API
    • +
    +
  • HAL + + + + I2C update
  • +
      +
    • I2C API + changes for MISRA-C 2012 + compliancy:
    • +
        +
      • Rename + HAL_I2C_Master_Sequential_Transmit_IT() + to + HAL_I2C_Master_Seq_Transmit_IT()
      • +
      • Rename + HAL_I2C_Master_Sequentiel_Receive_IT() + to + HAL_I2C_Master_Seq_Receive_IT()
      • +
      • Rename + HAL_I2C_Slave_Sequentiel_Transmit_IT() + to + HAL_I2C_Slave_Seq_Transmit_IT() +
      • +
      • Rename + HAL_I2C_Slave_Sequentiel_Receive_DMA() + to + HAL_I2C_Slave_Seq_Receive_DMA()
      • +
      +
    • SMBUS defined + flags are removed as not used + by the HAL I2C driver
    • +
        +
      • I2C_FLAG_SMBALERT
      • +
      • I2C_FLAG_TIMEOUT
      • +
      • I2C_FLAG_PECERR
      • +
      • I2C_FLAG_SMBHOST
      • +
      • I2C_FLAG_SMBDEFAULT
      • +
      +
    • Add support + of I2C repeated start feature + in DMA Mode:
    • +
        +
      • With the + following new API's
      • +
          +
        • HAL_I2C_Master_Seq_Transmit_DMA()
        • +
        • HAL_I2C_Master_Seq_Receive_DMA()
        • +
        • HAL_I2C_Slave_Seq_Transmit_DMA()
        • +
        • HAL_I2C_Slave_Seq_Receive_DMA()
        • +
        +
      +
    • Add new I2C + transfer options to easy + manage the sequential transfers
    • +
        +
      • I2C_FIRST_AND_NEXT_FRAME
      • +
      • I2C_LAST_FRAME_NO_STOP
      • +
      • I2C_OTHER_FRAME
      • +
      • I2C_OTHER_AND_LAST_FRAME
      • +
      +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • I2C API + changes for MISRA-C 2012 + compliancy:
    • +
        +
      • Rename + HAL_FMPI2C_Master_Sequential_Transmit_IT() + to + HAL_FMPI2C_Master_Seq_Transmit_IT()
      • +
      • Rename + HAL_FMPI2C_Master_Sequentiel_Receive_IT() + to + HAL_FMPI2C_Master_Seq_Receive_IT()
      • +
      • Rename + HAL_FMPI2C_Master_Sequentiel_Transmit_DMA() + to + HAL_FMPI2C_Master_Seq_Transmit_DMA() +
      • +
      • Rename + HAL_FMPI2C_Master_Sequentiel_Receive_DMA() + to + HAL_FMPI2C_Master_Seq_Receive_DMA()
      • +
      +
    • Rename + FMPI2C_CR1_DFN to + FMPI2C_CR1_DNF for more + compliance with Reference + Manual regarding registers and + bit definition naming
    • +
    • Add support + of I2C repeated start feature + in DMA Mode:
    • +
        +
      • With the + following new API's
      • +
          +
        • HAL_FMPI2C_Master_Seq_Transmit_DMA()
        • +
        • HAL_FMPI2C_Master_Seq_Receive_DMA()
        • +
        • HAL_FMPI2C_Slave_Seq_Transmit_DMA()
        • +
        • HAL_FMPI2C_Slave_Seq_Receive_DMA()
        • +
        +
      +
    +
  • HAL + + + + FLASH update
  • +
      +
    • Update the FLASH_OB_GetRDP() + API to return the correct RDP + level
    • +
    +
  • HAL  + RCC + update
  • +
      +
    • Remove GPIOD + CLK macros for STM32F412Cx + devices (X = D)
    • +
    • Remove GPIOE + CLK macros for + STM32F412Rx\412Cx devices: (X + = E)
    • +
    • Remove + GPIOF/G CLK macros for + STM32F412Vx\412Rx\412Cx + devices (X= F or G)
    • +
        +
      • __HAL_RCC_GPIOX_CLK_ENABLE()
      • +
      • __HAL_RCC_GPIOX_CLK_DISABLE()
      • +
      • __HAL_RCC_GPIOX_IS_CLK_ENABLED()
      • +
      • __HAL_RCC_GPIOX_IS_CLK_DISABLED()
      • +
      • __HAL_RCC_GPIOX_FORCE_RESET()
      • +
      +
    +
  • HAL + + + + RNG update
  • +
      +
    • Update to + manage RNG error code:
    • +
        +
      • Add ErrorCode + parameter in HAL RNG Handler + structure
      • +
      +
    +
  • LL + + + + ADC update
  • +
      +
    • Add + __LL_ADC_CALC_TEMPERATURE() + helper macro to calculate the + temperature (unit: degree + Celsius) from ADC conversion + data of internal temperature + sensor.
    • +
    • Fix ADC + channels configuration issues + on STM32F413xx/423xx devices
    • +
        +
      • To allow + possibility to switch + between VBAT and TEMPERATURE + channels configurations
      • +
      +
    • HAL_ADC_Start(), HAL_ADC_Start_IT() + + + + + and HAL_ADC_Start_DMA() + + + + + update to prevention from + starting ADC2 or ADC3 once + multimode is enabled
    • +
    +
  • HAL + + + + DFSDM  + + + + update
  • +
      +
    • General + updates to be compliant with + DFSDM bits naming used in + CMSIS files.
    • +
    +
  • HAL + + + + CAN  + + + + update
  • +
      +
    • Update + possible values list for FilterActivation + parameter in CAN_FilterTypeDef + structure
    • +
        +
      • CAN_FILTER_ENABLE + + + + + instead of ENABLE
      • +
      • CAN_FILTER_DISABLE + + + + + instead of DISABLE
      • +
      +
    +
  • HAL + + + + CEC  + + + + update
  • +
      +
    • Update HAL + CEC State management method:
    • +
        +
      • Remove HAL_CEC_StateTypeDef + structure parameters
      • +
      • Add new + defines for CEC states
      • +
      +
    +
  • HAL + + + + DMA  + + + + update
  • +
      +
    • Add clean of + callbacks in HAL_DMA_DeInit() + API
    • +
    +
  • HAL + + + + DMA2D  + + + + update
  • +
      +
    • Remove unused + DMA2D_ColorTypeDef structure + to be compliant with MISRAC + 2012 Rule 2.3
    • +
    • General + update to use dedicated + defines for + DMA2D_BACKGROUND_LAYER and + DMA2D_FOREGROUND_LAYER instead + of numerical values: 0/1.
    • +
    +
  • HAL + + + + DSI  + + + + update
  • +
      +
    • Fix read + multibyte issue: remove extra + call to __HAL_UNLOCK__ from DSI_ShortWrite() + API.
    • +
    +
+
    +
  • HAL/LL + + + + RTC update
  • +
+
    +
      +
    • HAL/ LL drivers + optimization
    • +
        +
      • HAL driver: + remove unused variables
      • +
      • LL driver: + getter APIs optimization
      • +
      +
    +
  • HAL + + + + PWR update
  • +
      +
    • Remove the + followings API's as feature + not supported by + STM32F469xx/479xx devices
    • +
        +
      • HAL_PWREx_EnableWakeUpPinPolarityRisingEdge()
      • +
      • HAL_PWREx_EnableWakeUpPinPolarityRisingEdge()
      • +
      +
    +
  • HAL + + + + SPI update
  • +
      +
    • Update HAL_SPI_StateTypeDef + structure to add new state: + HAL_SPI_STATE_ABORT
    • +
    +
  • HAL/LL + + + + TIM update
  • +
      +
    • Add new AutoReloadPreload + field in TIM_Base_InitTypeDef + structure
    • +
        +
      • Refer to + the TIM examples to identify + the changes +
      • +
      +
    • Move the + following TIM structures from + stm32f4xx_hal_tim_ex.h into + stm32f4xx_hal_tim.h
    • +
        +
      • TIM_MasterConfigTypeDef
      • +
      • TIM_BreakDeadTimeConfigTypeDef
      • +
      +
    • Add new TIM + Callbacks API's:
    • +
        +
      • HAL_TIM_PeriodElapsedHalfCpltCallback()
      • +
      • HAL_TIM_IC_CaptureHalfCpltCallback()
      • +
      • HAL_TIM_PWM_PulseFinishedHalfCpltCallback()
      • +
      • HAL_TIM_TriggerHalfCpltCallback()
      • +
      +
    • TIM API + changes for MISRA-C 2012 + compliancy:
    • +
        +
      • Rename HAL_TIM_SlaveConfigSynchronization + to HAL_TIM_SlaveConfigSynchro
      • +
      • Rename HAL_TIM_SlaveConfigSynchronization_IT + to HAL_TIM_SlaveConfigSynchro_IT
      • +
      • Rename HAL_TIMEx_ConfigCommutationEvent + to HAL_TIMEx_ConfigCommutEvent
      • +
      • Rename HAL_TIMEx_ConfigCommutationEvent_IT + to HAL_TIMEx_ConfigCommutEvent_IT
      • +
      • Rename HAL_TIMEx_ConfigCommutationEvent_DMA + to HAL_TIMEx_ConfigCommutEvent_DMA
      • +
      • Rename HAL_TIMEx_CommutationCallback + to HAL_TIMEx_CommutCallback
      • +
      • Rename HAL_TIMEx_DMACommutationCplt + to TIMEx_DMACommutationCplt
      • +
      +
    +
+
    +
  • HAL/LL + + + + USB update
  • +
      +
    • Rework USB + interrupt handler and improve + HS DMA support in Device mode
    • +
    • Fix BCD + handling fr OTG + instance in device mode
    • +
    • cleanup + reference to low speed in + device mode
    • +
    • allow writing + TX FIFO in case of transfer + length is equal to available + space in the TX FIFO
    • +
    • Fix Toggle + OUT interrupt channel in host + mode
    • +
    • Update USB + OTG max number of endpoints (6 + FS and 9 HS instead of 5 and + 8)
    • +
    • Update USB + OTG IP to enable internal + transceiver when starting USB + device after committee BCD negotiation
    • +
    +
  • LL + + + + IWDG update
  • +
      +
    • Update LL + inline macros to use IWDGx + parameter instead of IWDG + instance defined in CMSIS device
    • +
    +
+

V1.7.4 + + + + / 02-February-2018

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL update
  • +
      +
    • Update UNUSED() + macro implementation to avoid + GCC warning
    • +
        +
      • The warning + is detected when the UNUSED() + macro is called from C++ + file
      • +
      +
    • Update to + make RAMFUNC define as generic + type instead of HAL_StatusTypdef + type.
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • Update + the prototypes of the + following APIs after change on + RAMFUNC defines 
    • +
        +
      • HAL_FLASHEx_StopFlashInterfaceClk()
      • +
      • HAL_FLASHEx_StartFlashInterfaceClk()
      • +
      • HAL_FLASHEx_EnableFlashSleepMode()
      • +
      • HAL_FLASHEx_DisableFlashSleepMode()
      • +
      +
    +
  • HAL + + + + SAI update
  • +
      +
    • Update HAL_SAI_DMAStop() + and HAL_SAI_Abort() + + + + + process to fix the lock/unlock + audio issue
    • +
    +
+

V1.7.3 + + + + / 22-December-2017

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • The + + + + following changes done on the + HAL drivers require an update + on the application code based + on older HAL versions
  • +
      +
    • Rework of + HAL CAN driver + (compatibility break) 
    • +
        +
      • A new HAL + CAN driver has been + redesigned with new APIs, to + bypass limitations on CAN + Tx/Rx FIFO management + present with previous HAL + CAN driver version.
      • +
      • The new HAL + CAN driver is the + recommended version. It is + located as usual in + Drivers/STM32F4xx_HAL_Driver/Src + and + Drivers/STM32f4xx_HAL_Driver/Inc + folders. It can be enabled + through switch + HAL_CAN_MODULE_ENABLED in + stm32f4xx_hal_conf.h
      • +
      • The legacy + HAL CAN driver is also + present in the release in + Drivers/STM32F4xx_HAL_Driver/Src/Legacy + + + + and + Drivers/STM32F4xx_HAL_Driver/Inc/Legacy + folders for software + compatibility reasons. Its + usage is not recommended as + deprecated. It can + however be enabled through + switch + HAL_CAN_LEGACY_MODULE_ENABLED + in stm32f4xx_hal_conf.h
      • +
      +
    +
  • HAL update
  • +
      +
    • Update HAL + driver to allow user to change + systick + period to 1ms, 10 ms + or 100 ms :
    • +
        +
      • Add the + following API's + + + + :  
      • +
          +
        • HAL_GetTickPrio(): + Returns a tick priority.
        • +
        • HAL_SetTickFreq(): Sets + new tick frequency.
        • +
        • HAL_GetTickFreq(): + Returns tick frequency.
        • +
        +
      • Add HAL_TickFreqTypeDef + enumeration for the + different Tick Frequencies: + 10 Hz, 100 Hz and 1KHz + (default).
      • +
      +
    +
  • HAL + + + + CAN update
  • +
      +
    • Fields of CAN_InitTypeDef + structure are reworked:
    • +
        +
      • SJW to SyncJumpWidth, + BS1 to TimeSeg1, BS2 to + TimeSeg2, TTCM to TimeTriggeredMode, + ABOM to AutoBusOff, + AWUM to AutoWakeUp, + NART to AutoRetransmission + (inversed), RFLM to ReceiveFifoLocked + and TXFP to TransmitFifoPriority
      • +
      +
    • HAL_CAN_Init() is split + into both HAL_CAN_Init() + + + + + and HAL_CAN_Start() + + + + + API's
    • +
    • HAL_CAN_Transmit() is replaced + by HAL_CAN_AddTxMessage() + + + + + to place Tx Request, then HAL_CAN_GetTxMailboxesFreeLevel() + + + + + for polling until completion.
    • +
    • HAL_CAN_Transmit_IT() is replaced + by HAL_CAN_ActivateNotification() + + + + + to enable transmit IT, then HAL_CAN_AddTxMessage() + + + + + for place Tx request.
    • +
    • HAL_CAN_Receive() is replaced + by HAL_CAN_GetRxFifoFillLevel() + + + + + for polling until reception, + then HAL_CAN_GetRxMessage() + + + + +
      + to get Rx message.
    • +
    • HAL_CAN_Receive_IT() is replaced + by HAL_CAN_ActivateNotification() to + + + + + enable receive IT, then HAL_CAN_GetRxMessage()
      + in the receivecallback + to get Rx message
    • +
    • HAL_CAN_Slepp() is renamed + as HAL_CAN_RequestSleep()
    • +
    • HAL_CAN_TxCpltCallback() is split + into + HAL_CAN_TxMailbox0CompleteCallback(), +HAL_CAN_TxMailbox1CompleteCallback() +and HAL_CAN_TxMailbox2CompleteCallback().
    • +
    • HAL_CAN_RxCpltCallback is split + into HAL_CAN_RxFifo0MsgPendingCallback() + and + HAL_CAN_RxFifo1MsgPendingCallback().
    • +
    • More complete + "How to use the new driver" is + detailed in the driver header + section itself.
    • +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Add new + option + FMPI2C_LAST_FRAME_NO_STOP for + the sequential transfer management
    • +
        +
      • This option + allows to manage a restart + condition after several call + of the same master + sequential interface. 
      • +
      +
    +
  • HAL + + + + RCC update
  • +
      +
    • Add new HAL macros
    • +
        +
      • __HAL_RCC_GET_RTC_SOURCE() + allowing to get the RTC + clock source
      • +
      • __HAL_RCC_GET_RTC_HSE_PRESCALER() + allowing to get the HSE + clock divider for RTC + peripheral
      • +
      +
    • Ensure reset + of CIR and CSR registers when + issuing HAL_RCC_DeInit()/LL_RCC_DeInit + functions
    • +
    • Update HAL_RCC_OscConfig() to + + + + + keep backup domain enabled + when configuring + respectively LSE and RTC + clock source
    • +
    • Add new HAL + interfaces allowing to control + the activation or deactivation + of PLLI2S and PLLSAI:
    • +
        +
      • HAL_RCCEx_EnablePLLI2S()
      • +
      • HAL_RCCEx_DisablePLLI2S()
      • +
      • HAL_RCCEx_EnablePLLSAI()
      • +
      • HAL_RCCEx_DisablePLLSAI()
      • +
      +
    +
+
    +
  • LL + + + + RCC update 
  • +
      +
    • Add new LL + RCC macro
    • +
        +
      • LL_RCC_PLL_SetMainSource() allowing + to configure PLL main clock + source
      • +
      +
    +
  • LL + + + + FMC / LL FSMC update
  • +
      +
    • Add clear of + the PTYP bit to select the + PCARD mode in FMC_PCCARD_Init() + / FSMC_PCCARD_Init()
    • +
    +
+

V1.7.2 + + + + / 06-October-2017

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Fix + compilation warning with + GCC compiler
  • +
  • Remove + + + + Date and version + from header files
  • +
  • Update + + + + HAL drivers to refer to the + new CMSIS bit position + defines instead of usage the + POSITION_VAL() + macro
  • +
  • HAL + + + + Generic update
  • +
      +
    • stm32f4xx_hal_def.h + + + + file changes: 
    • +
        +
      • Update + __weak and __packed defined + values for ARM compiler
      • +
      • Update + __ALIGN_BEGIN and + __ALIGN_END defined values + for ARM compiler
      • +
      +
    • stm32f4xx_ll_system.h + + + + + file: + add LL_SYSCFG_REMAP_SDRAM + define
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • Fix wrong + definition of ADC channel + temperature sensor for + STM32F413xx and STM32F423xx + devices.
    • +
    +
  • HAL + + + + DMA update
  • +
      +
    • Update values + + + + for the following defines: + DMA_FLAG_FEIF0_4 and + DMA_FLAG_DMEIF0_4 
    • +
    +
  • HAL + + + + DSI update
  • +
      +
    • Fix Extra + warning with SW4STM32 compiler
    • +
    • Fix DSI + display issue when using EWARM + w/ high level optimization 
    • +
    • Fix + MISRAC errors
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • HAL_FLASH_Unlock() update to + return state error when the + FLASH is already unlocked
    • +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Update + Interface APIs headers to + remove confusing message about + device address
    • +
    • Update + FMPI2C_WaitOnRXNEFlagUntilTimeout() + to resolve a race condition + between STOPF and RXNE Flags
    • +
    • Update + FMPI2C_TransferConfig() + to fix wrong bit management.
    • +
    • Update code + comments to use DMA stream + instead of DMA channel
    • +
    +
+
    +
  • HAL + + + + PWR update
  • +
      +
    • HAL_PWR_EnableWakeUpPin() update + description to add support of + PWR_WAKEUP_PIN2 and + PWR_WAKEUP_PIN3
    • +
    +
  • HAL + + + + NOR update
  • +
      +
    • Add the + support of STM32F412Rx devices
    • +
    +
  • HAL + + + + I2C update
  • +
      +
    • Update + Interface APIs headers to + remove confusing mesage + about device address
    • +
    • Update + I2C_MasterReceive_RXNE() + and I2C_MasterReceive_BTF() + static APIs to fix bad + Handling of NACK in I2C master + receive process.
    • +
    +
+
    +
  • HAL + + + + RCC update
  • +
      +
    • Update HAL_RCC_GetOscConfig() + API to:
    • +
        +
      • set PLLR in + the RCC_OscInitStruct
      • +
      • check on + null pointer
      • +
      +
    • Update HAL_RCC_ClockConfig() + API to:
    • +
        +
      • check on + null pointer
      • +
      • optimize code + + + + size by updating the + handling method of the SWS bits
      • +
      • update to use  + + + + + __HAL_FLASH_GET_LATENCY() + + + + flash macro instead of using + direct register access + to LATENCY bits in + FLASH ACR register.
      • +
      +
    • Update HAL_RCC_DeInit() +  and LL_RCC_DeInit() + + + + + APIs to
    • +
        +
      • Be able to + return HAL/LL status
      • +
      • Add checks + for HSI, PLL and PLLI2S +  ready + before modifying RCC CFGR + registers
      • +
      • Clear all + interrupt falgs
      • +
      • Initialize + systick + interrupt period
      • +
      +
    • Update HAL_RCC_GetSysClockFreq() + to avoid risk of rounding + error which may leads to a + wrong returned value. 
    • +
    +
+

 

+

 

+
    +
  • HAL + + + + RNG update
  • +
      +
    • HAL_RNG_Init() remove + Lock()/Unlock()
    • +
    +
  • HAL + + + + MMC update
  • +
      +
    • HAL_MMC_Erase() + API: add missing () to + fix compilation warning + detected with SW4STM32 when + extra feature is enabled.
    • +
    +
  • HAL + + + + RTC update
  • +
      +
    • HAL_RTC_Init() API: update + to force the wait for synchro + before setting TAFCR register + when BYPSHAD bit in CR + register is 0.
    • +
    +
  • HAL + + + + SAI update
  • +
      +
    • Update HAL_SAI_DMAStop() + API to flush fifo + after disabling SAI
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Update I2S + DMA fullduplex process to + handle I2S Rx and Tx DMA Half + transfer complete callback
    • +
    +
  • HAL + + + + TIM update
  • +
      +
    • Update HAL_TIMEx_OCN_xxxx() + and HAL_TIMEx_PWMN_xxx() + + + + + API description to remove + support of TIM_CHANNEL_4
    • +
    +
  • LL + + + + DMA update
  • +
      +
    • Update to + clear DMA flags using WRITE_REG() + instead SET_REG() API to avoid + read access to the IFCR + register that is write only.
    • +
    +
  • LL + + + + RTC update
  • +
      +
    • Fix warning + with static analyzer
    • +
    +
  • LL + + + + USART update
  • +
      +
    • Add assert + macros to check USART BaudRate + register
    • +
    +
  • LL + + + + I2C update
  • +
      +
    • Rename + IS_I2C_CLOCK_SPEED() + and IS_I2C_DUTY_CYCLE() + respectively to + IS_LL_I2C_CLOCK_SPEED() and + IS_LL_I2C_DUTY_CYCLE() to + avoid incompatible macros + redefinition.
    • +
    +
  • LL + + + + TIM update
  • +
      +
    • Update LL_TIM_EnableUpdateEvent() + API to clear UDIS bit in TIM + CR1 register instead of + setting it.
    • +
    • Update LL_TIM_DisableUpdateEvent() + API to set UDIS bit in TIM CR1 + register instead of clearing + it.
    • +
    +
  • LL + + + + USART update
  • +
      +
    • Fix MISRA + error w/ IS_LL_USART_BRR() + macro
    • +
    • Fix wrong + check when UART10 instance is + used
    • +
    +
+

V1.7.1 + + + + / 14-April-2017

+

Main Changes

+
    +
  • Update + + + + CHM UserManuals + to support LL drivers
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL + + + + CAN update
  • +
      +
    • Add + management of overrun + error. 
    • +
    • Allow + possibility to receive + messages from the 2 RX FIFOs + in parallel via interrupt.
    • +
    • Fix message + + + + lost issue with specific + sequence of transmit requests.
    • +
    • Handle + transmission failure with + error callback, when NART is + enabled.
    • +
    • Add + __HAL_CAN_CANCEL_TRANSMIT() + call to abort transmission + when timeout is reached
    • +
    +
+
    +
  • HAL + + + + PWR update
  • +
      +
    • HAL_PWREx_EnterUnderDriveSTOPMode() API: remove + check on UDRDY flag
    • +
    +
+
    +
  • LL + + + + ADC update
  • +
      +
    • Fix wrong ADC + group injected sequence configuration
    • +
        +
      • LL_ADC_INJ_SetSequencerRanks() and LL_ADC_INJ_GetSequencerRanks() + + + + + API's update to take in + consideration the ADC number + of conversions
      • +
      • Update + the defined values for + ADC group injected seqencer + ranks 
      • +
      +
    +
+

V1.7.0 + + + + / 17-February-2017

+

Main Changes

+
    +
  • Add + + + + Low Layer drivers allowing + performance and footprint optimization
  • +
      +
    • Low Layer drivers + APIs provide register level + programming: require deep + knowledge of peripherals + described in STM32F4xx + Reference Manuals
    • +
    • Low Layer + drivers are available for: + ADC, Cortex, CRC, DAC, + DMA, DMA2D, EXTI, GPIO, I2C, + IWDG, LPTIM, PWR, RCC, RNG, + RTC, SPI, TIM, USART, WWDG + peripherals and additionnal + Low Level Bus, System and + Utilities APIs.
    • +
    • Low Layer drivers + APIs are implemented as static + inline function in new Inc/stm32f4xx_ll_ppp.h files + + + + + for PPP peripherals, there is + no configuration file and each stm32f4xx_ll_ppp.h file + + + + + must be included in user code.
    • +
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Fix extra + + + + warnings with GCC compiler
  • +
  • HAL + drivers clean up: remove + double casting 'uint32_t' and 'U'
  • +
  • Add + new HAL + + + + MMC driver
  • +
  • The + + + + following changes done on the + HAL drivers require an update + on the application code based + on older HAL versions
  • +
      +
    • HAL SD update
    • +
        +
      • Overall + rework of the driver for a + more + efficient implementation
      • +
          +
        • Modify + initialization API and structures
        • +
        • Modify + Read / Write sequences: + separate transfer process + and SD Cards state management 
        • +
        • Adding + interrupt mode for Read / + Write operations
        • +
        • Update + the HAL_SD_IRQHandler + function by optimizing the + management of interrupt errors
        • +
        +
      • Refer to + the following example to + identify the changes: BSP + example and USB_Device/MSC_Standalone + application
      • +
      +
    • HAL NAND update
    • +
        +
      • Modify NAND_AddressTypeDef, + NAND_DeviceConfigTypeDef + and NAND_HandleTypeDef + structures fields
      • +
      • Add new HAL_NAND_ConfigDevice + API
      • +
      +
    • HAL DFSDM update
    • +
        +
      • Add + support of Multichannel + Delay feature
      • +
          +
        • Add HAL_DFSDM_ConfigMultiChannelDelay + API
        • +
        • The + following APIs are moved + to internal static + functions: HAL_DFSDM_ClockIn_SourceSelection, + HAL_DFSDM_ClockOut_SourceSelection, + HAL_DFSDM_DataInX_SourceSelection + (X=0,2,4,6), HAL_DFSDM_BitStreamClkDistribution_Config
        • +
        +
      +
    • HAL I2S update
    • +
        +
      • Add specific + + + + + callback API to manage I2S + full duplex end of transfer + process:
      • +
          +
        • HAL_I2S_TxCpltCallback() + and + HAL_I2S_RxCpltCallback() + API's will be replaced + with only + HAL_I2SEx_TxRxCpltCallback() + API. 
        • +
        +
      +
    +
  • HAL + + + + update
  • +
      +
    • Modifiy default HAL_Delay + implementation to guarantee + minimum delay 
    • +
    +
  • HAL + + + + Cortex update
  • +
      +
    • Move HAL_MPU_Disable() + and HAL_MPU_Enable() + + + + + from stm32f4xx_hal_cortex.h to + stm32f4xx_hal_cortex.c
    • +
    • Clear the + whole MPU control register + in HAL_MPU_Disable() + API
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • IS_FLASH_ADDRESS() + macro update to support OTP + range
    • +
    • FLASH_Program_DoubleWord(): Replace + 64-bit accesses with 2 + double-words operations
    • +
    +
  • LL + + + + GPIO update
  • +
      +
    • Update + IS_GPIO_PIN() + macro implementation to be + more safe
    • +
    +
  • LL + + + + RCC update
  • +
      +
    • Update + IS_RCC_PLLQ_VALUE() + macro implementation: the + minimum accepted value is + 2 instead of 4
    • +
    • Rename + RCC_LPTIM1CLKSOURCE_PCLK + define to + RCC_LPTIM1CLKSOURCE_PCLK1
    • +
    • Fix + compilation issue w/ + __HAL_RCC_USB_OTG_FS_IS_CLK_ENABLED() + and + __HAL_RCC_USB_OTG_FS_IS_CLK_DISABLED() + macros for STM32F401xx devices
    • +
    • Add the + following is clock + enabled macros for STM32F401xx + devices
    • +
        +
      •  __HAL_RCC_SDIO_IS_CLK_ENABLED()
      • +
      • __HAL_RCC_SPI4_IS_CLK_ENABLED()
      • +
      • __HAL_RCC_TIM10_IS_CLK_ENABLED()
      • +
      +
    • Add the + following is clock + enabled macros for STM32F410xx + devices
    • +
        +
      •  __HAL_RCC_CRC_IS_CLK_ENABLED()
      • +
      • __HAL_RCC_RNG_IS_CLK_ENABLED()
      • +
      +
    • Update HAL_RCC_DeInit() + to reset the RCC clock + configuration to the default + reset state.
    • +
    • Remove macros + to configure BKPSRAM from + STM32F401xx devices 
    • +
    • Update to + refer to AHBPrescTable[] + and APBPrescTable[] + + + + + tables defined in + system_stm32f4xx.c file + instead of APBAHBPrescTable[] + + + + + table.
    • +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Add + FMPI2C_FIRST_AND_NEXT_FRAME + define in Sequential + Transfer Options
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • HAL_ADCEx_InjectedConfigChannel(): update the + external trigger injected + condition
    • +
    +
  • HAL + + + + DMA update
  • +
      +
    • HAL_DMA_Init(): update to + check compatibility between + FIFO threshold level and size + of the memory burst 
    • +
    +
  • HAL + + + + QSPI update
  • +
      +
    • QSPI_HandleTypeDef structure: + Update transfer parameters on + uint32_t instead of uint16_t
    • +
    +
  • HAL + + + + UART/USART/IrDA/SMARTCARD update
  • +
      +
    • DMA Receive + process; the code has been + updated to clear the USART + OVR flag before + enabling DMA receive + request.
    • +
    • UART_SetConfig() update to + manage correctly USART6 + instance that is not available + on STM32F410Tx devices
    • +
    +
  • HAL + + + + CAN update
  • +
      +
    • Remove Lock + mechanism from HAL_CAN_Transmit_IT() + and HAL_CAN_Receive_IT() + + + + + processes
    • +
    +
  • HAL + + + + TIM update
  • +
      +
    • Add + __HAL_TIM_MOE_DISABLE_UNCONDITIONALLY() + macro to disable Master output + without check on TIM channel + state. 
    • +
    • Update HAL_TIMEx_ConfigBreakDeadTime() + to fix TIM BDTR register + corruption.
    • +
    +
  • HAL + + + + I2C update
  • +
      +
    • Update + HAL_I2C_Master_Transmit() + and HAL_I2C_Slave_Transmit() + to avoid sending extra + bytes at the end of the + transmit processes
    • +
    • Update + HAL_I2C_Mem_Read() + API to fix wrong check on + misused parameter “Size”
    • +
    • Update + I2C_MasterReceive_RXNE() + and I2C_MasterReceive_BTF() + static APIs to enhance Master + sequential reception process.
    • +
    +
  • HAL + + + + SPI update
  • +
      +
    • Add transfer + abort APIs and associated + callbacks in interrupt mode
    • +
        +
      • HAL_SPI_Abort()
      • +
      • HAL_SPI_Abort_IT()
      • +
      • HAL_SPI_AbortCpltCallback()
      • +
      +
    +
  • HAL + + + + I2S update
  • +
      +
    • Add specific + + + + + callback API to manage I2S + full duplex end of transfer + process:
    • +
        +
      • HAL_I2S_TxCpltCallback() + and HAL_I2S_RxCpltCallback() + API's will be replaced with + only + HAL_I2SEx_TxRxCpltCallback() + API. 
      • +
      +
    • Update I2S + Transmit/Receive polling + process to manage Overrun + and Underrun errors
    • +
    • Move + the I2S clock input + frequency calculation to + HAL RCC driver.
    • +
    • Update the + HAL I2SEx driver to keep only + full duplex feature.
    • +
    • HAL_I2S_Init() + API updated to
    • +
        +
      • Fix wrong + I2S clock calculation when + PCM mode is used.
      • +
      • Return + state HAL_I2S_ERROR_PRESCALER when + the I2S clock is wrongly configured
      • +
      +
    +
+
    +
  • HAL + + + + LTDC update
  • +
      +
    • Optimize HAL_LTDC_IRQHandler() + function by using direct + register read
    • +
    • Rename the + following API's
    • +
        +
      • HAL_LTDC_Relaod() by HAL_LTDC_Reload() 
      • +
      • HAL_LTDC_StructInitFromVideoConfig() by HAL_LTDCEx_StructInitFromVideoConfig()
      • +
      • HAL_LTDC_StructInitFromAdaptedCommandConfig() by HAL_LTDCEx_StructInitFromAdaptedCommandConfig()
      • +
      +
    • Add new + defines for LTDC layers + (LTDC_LAYER_1 / LTDC_LAYER_2)
    • +
    • Remove unused + asserts
    • +
    +
  • HAL + + + + USB PCD + update
  • +
      +
    • Flush all TX + FIFOs on USB Reset
    • +
    • Remove Lock + mechanism from HAL_PCD_EP_Transmit() + and HAL_PCD_EP_Receive() + + + + + API's
    • +
    +
+
    +
  • LL + + + + USB update
  • +
      +
    • Enable DMA + Burst mode for USB OTG HS
    • +
    • Fix SD card + detection issue
    • +
    +
  • LL + + + + SDMMC update
  • +
      +
    • Add new SDMMC_CmdSDEraseStartAdd, + SDMMC_CmdSDEraseEndAdd, + SDMMC_CmdOpCondition + and SDMMC_CmdSwitch + functions
    • +
    +
+

V1.6.0 + + + + / 04-November-2016

+

Main Changes

+
    +
  • Add support of STM32F413xx + and STM32F423xx + devices
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • HAL + + + + CAN update
  • +
      +
    • Update to add + the support of 3 CAN management
    • +
    +
  • HAL + + + + CRYP update
  • +
      +
    • Update to add + the support of AES features
    • +
    +
  • HAL + + + + DFSDM update
  • +
      +
    • Add + definitions for new external + trigger filters
    • +
    • Add + definition for new Channels + 4, 5, 6 and 7
    • +
    • Add + functions and API for Filter + state configuration and management
    • +
    • Add new + functions: 
    • +
        +
      • HAL_DFSDM_BitstreamClock_Start()
      • +
      • HAL_DFSDM_BitstreamClock_Stop()
      • +
      • HAL_DFSDM_BitStreamClkDistribution_Config(
      • +
      +
    +
  • HAL + + + + DMA
  • +
      +
    • Add the + support of DMA Channels from + 8 to 15
    • +
    • Update HAL_DMA_DeInit() + function with the check on + DMA stream instance
    • +
    +
  • HAL + + + + DSI update
  • +
+
    +
      +
    • Update HAL_DSI_ConfigHostTimeouts() + and HAL_DSI_Init() + + + + + functions to avoid scratch in + DSI_CCR register
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • Enhance FLASH_WaitForLastOperation() + function implementation
    • +
    • Update + __HAL_FLASH_GET_FLAG() + macro implementation
    • +
    +
  • HAL + + + + GPIO update
  • +
      +
    • Add + specific alternate functions + definitions
    • +
    +
  • HAL + + + + I2C update
  • +
      +
    • Update I2C_DMAError() + function implementation to + ignore DMA FIFO error
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Enhance + HAL_I2S_Init() + implementation to test on + PCM_SHORT and PCM_LONG + standards
    • +
    +
  • HAL + + + + IRDA update
  • +
      +
    • Add new + functions and call backs for + Transfer Abort
    • +
        +
      • HAL_IRDA_Abort()
      • +
      • HAL_IRDA_AbortTransmit()
      • +
      • HAL_IRDA_AbortReceive()
      • +
      • HAL_IRDA_Abort_IT()
      • +
      • HAL_IRDA_AbortTransmit_IT()
      • +
      • HAL_IRDA_AbortReceive_IT()
      • +
      • HAL_IRDA_AbortCpltCallback()
      • +
      • HAL_IRDA_AbortTransmitCpltCallback()
      • +
      +
    +
+
    +
      +
        +
      • HAL_IRDA_AbortReceiveCpltCallback()
      • +
      +
    +
  • HAL + + + + PCD update
  • +
+
    +
      +
    • Update HAL_PCD_GetRxCount() +  function implementation
    • +
    +
  • HAL + + + + RCC update
  • +
      +
    • Update + __HAL_RCC_HSE_CONFIG() + macro implementation
    • +
    • Update __HAL_RCC_LSE_CONFIG() + macro implementation
    • +
    +
  • HAL + + + + SMARTCARD update
  • +
+
    +
      +
    • Add new + functions and call backs for + Transfer Abort
    • +
        +
      • HAL_ SMARTCARD_Abort()
      • +
      • HAL_ SMARTCARD_AbortTransmit()
      • +
      • HAL_ SMARTCARD_AbortReceive()
      • +
      • HAL_ SMARTCARD_Abort_IT()
      • +
      • HAL_ SMARTCARD_AbortTransmit_IT()
      • +
      • HAL_ SMARTCARD_AbortReceive_IT()
      • +
      • HAL_ SMARTCARD_AbortCpltCallback()
      • +
      • HAL_ SMARTCARD_AbortTransmitCpltCallback()
      • +
      • HAL_ SMARTCARD_AbortReceiveCpltCallback()
      • +
      +
    +
  • HAL + + + + TIM update
  • +
      +
    • Update HAL_TIMEx_RemapConfig() + function to manage TIM + internal trigger remap: + LPTIM or TIM3_TRGO
    • +
    +
  • HAL + + + + UART update
  • +
      +
    • Add + Transfer abort functions and + callbacks
    • +
    +
  • HAL + + + + USART update
  • +
      +
    • Add + Transfer abort functions and + callbacks
    • +
    +
+

V1.5.2 + + + + / 22-September-2016

+

Main Changes

+
    +
  • HAL + + + + I2C update
  • +
      +
    • Fix wrong + behavior in consecutive + transfers in case of single + byte transmission + (Master/Memory Receive
      + interfaces)
    • +
    • Update + HAL_I2C_Master_Transmit_DMA() + / + HAL_I2C_Master_Receive_DMA()/ + HAL_I2C_Slave_Transmit_DMA()
      + and + HAL_I2C_Slave_Receive_DMA() to + manage addressing phase + through interruption instead + of polling
    • +
    • Add + a check on I2C handle + state at start of all I2C + API's to ensure that I2C is ready
    • +
    • Update I2C + API's (Polling, IT and DMA + interfaces) to manage I2C XferSize + and XferCount + handle parameters instead of + API size parameter to help + user to get information of + counter in case of + error. 
    • +
    • Update Abort + functionality to manage DMA + use case
    • +
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Update to + disable Own Address + before setting the new Own + Address + configuration:
    • +
        +
      • Update + HAL_FMPI2C_Init() + to disable FMPI2C_OARx_EN + bit before any + configuration in OARx + registers
      • +
      +
    +
  • HAL + + + + CAN update
  • +
      +
    • Update CAN + receive processes to set CAN + RxMsg + FIFONumber + parameter
    • +
    +
  • HAL + + + + UART update
  • +
      +
    • Update UART + + + + handle TxXferCount + and RxXferCount parameters + + + + + as volatile to avoid + eventual issue with High Speed + optimization  
    • +
    +
+

V1.5.1 + + + + / 01-July-2016

+

Main Changes

+
    +
  • HAL + + + + GPIO update
  • +
      +
    • HAL_GPIO_Init()/HAL_GPIO_DeInit() + API's: + update GPIO_GET_INDEX() + macro implementation to + support all GPIO's
    • +
    +
  • HAL + + + + SPI update
  • +
      +
    • Fix + regression issue: + retore HAL_SPI_DMAPause() + and HAL_SPI_DMAResume() API's +
    • +
    +
  • HAL + + + + RCC update
  • +
      +
    • Fix FSMC + macros compilation warnings + with STM32F412Rx devices
    • +
    +
  • HAL + + + + DMA update
  • +
      +
    • HAL_DMA_PollFortransfer() API clean + up
      +
      +
    • +
    +
  • HAL + + + + PPP update(PPP refers to + IRDA, UART, USART and SMARTCARD)
  • +
      +
    • Update + + + + HAL_PPP_IRQHandler() + to add a check on interrupt + source before managing the + error 
    • +
    +
+
    +
  • HAL + + + + QSPI update
  • +
      +
    • Implement + workaround to fix the + limitation pronounced + + + + in + the Errata + sheet 2.1.8 section: + In some specific cases, + DMA2 data corruption + occurs when managing AHB + and APB2 peripherals in a + concurrent way
    • +
    +
+

V1.5.0 + + + + / 06-May-2016

+

Main Changes

+
    +
  • Add support of STM32F412cx, + + + + + STM32F412rx, STM32F412vx and + STM32F412zx devices
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Add + new HAL driver for DFSDM peripheral
  • +
  • Enhance + + + + HAL delay and time base + implementation:
  • +
      +
    • Add new + drivers + stm32f4xx_hal_timebase_rtc_alarm_template.c + and + stm32f4xx_hal_timebase_rtc_wakeup_template.c + which override the native HAL + time base functions (defined + as weak) to either use the RTC + as time base tick source. For + more details about the usage + of these drivers, please refer + to HAL\HAL_TimeBase_RTC + examples and + + + + + FreeRTOS-based + + + + + applications
    • +
    +
  • The + + + + following changes done on the + HAL drivers require an update + on the application code based + on HAL V1.4.4
  • +
      +
    • HAL UART, + USART, IRDA, SMARTCARD, SPI, + I2C,FMPI2C, + + + + + QSPI (referenced + as PPP here + + + + + below) drivers
    • +
        +
      • Add PPP + error management during DMA + process. This requires the + following updates + on user application:
      • +
          +
        • Configure + and enable the PPP IRQ in + HAL_PPP_MspInit() + function
        • +
        • In stm32f4xx_it.c + + + + + file, PPP_IRQHandler() + function: add + + + + + a call to HAL_PPP_IRQHandler() + + + + + function
        • +
        • Add and + customize the Error + Callback API: HAL_PPP_ErrorCallback()
        • +
        +
      +
    • HAL I2C, FMPI2C (referenced + as PPP here + + + + + below) drivers:
    • +
        +
      • Update to + avoid waiting on STOPF/BTF/AF + + + + + flag under DMA ISR by using + the PPP + + + + end of transfer interrupt in + the DMA transfer process. This + + + + + requires the following + updates on user + application:
      • +
          +
        • Configure + and enable the PPP IRQ in + HAL_PPP_MspInit() + function
        • +
        • In stm32f4xx_it.c + + + + + file, PPP_IRQHandler() + function: add + + + + + a call to HAL_PPP_IRQHandler() + + + + + function
        • +
        +
      +
    • HAL I2C driver:
    • +
        +
      • I2C + transfer processes IT + update: NACK during + addressing phase is managed + through I2C Error + interrupt instead of + HAL state
      • +
      +
    +
+
    +
      +
    • HAL IWDG driver: + rework overall driver for + better implementation
    • +
        +
      • Remove HAL_IWDG_Start(), HAL_IWDG_MspInit() + + + + + and HAL_IWDG_GetState() APIs
      • +
      +
    • HAL WWDG driver: + rework overall driver for + better implementation
    • +
        +
      • Remove HAL_WWDG_Start(), HAL_WWDG_Start_IT(), HAL_WWDG_MspDeInit() + + + + + and HAL_WWDG_GetState() + + + + + APIs 
      • +
      • Update + the HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg, + uint32_t counter) +  function and API +  by removing the +  "counter" parameter
      • +
      +
    • HAL QSPI + driver:  Enhance + the DMA transmit process + by using PPP TC + interrupt instead of waiting + on TC flag under DMA + ISR. This requires the + following updates on user + application:
    • +
        +
      • Configure + and enable the QSPI IRQ + in HAL_QSPI_MspInit() + function
      • +
      • In stm32f4xx_it.c + + + + + file, QSPI_IRQHandler() + function: add + + + + a call to HAL_QSPI_IRQHandler() + + + + + function
      • +
      +
    • HAL CEC + driver:  Overall + driver rework with + compatibility break versus + previous HAL version
    • +
        +
      • Remove HAL + CEC polling Process + functions: HAL_CEC_Transmit() + and HAL_CEC_Receive()
      • +
      • Remove HAL + CEC receive interrupt + process function HAL_CEC_Receive_IT() + and enable the "receive" +  mode during the Init + phase
      • +
      • Rename HAL_CEC_GetReceivedFrameSize() + funtion + to HAL_CEC_GetLastReceivedFrameSize()
      • +
      • Add new HAL + APIs: HAL_CEC_SetDeviceAddress() + and HAL_CEC_ChangeRxBuffer()
      • +
      • Remove + the 'InitiatorAddress' + field from the CEC_InitTypeDef + structure and manage + it as a parameter in + the HAL_CEC_Transmit_IT() + function
      • +
      • Add new + parameter 'RxFrameSize' + in HAL_CEC_RxCpltCallback() + function
      • +
      • Move CEC Rx + buffer pointer from CEC_HandleTypeDef + structure to CEC_InitTypeDef + structure
      • +
      +
    +
+
    +
  • HAL + + + + RCC update
  • +
      +
    • Update HAL_RCC_ClockConfig() + function to adjust the SystemCoreClock
    • +
    • Rename macros + and Literals:
    • +
        +
      • RCC_PERIPHCLK_CK48 by RCC_PERIPHCLK_CLK48
      • +
      • IS_RCC_CK48CLKSOURCE by + + + + + IS_RCC_CLK48CLKSOURCE
      • +
      • RCC_CK48CLKSOURCE_PLLSAIP + + + + + by RCC_CLK48CLKSOURCE_PLLSAIP
      • +
      • RCC_SDIOCLKSOURCE_CK48 + + + + by RCC_SDIOCLKSOURCE_CLK48
      • +
      • RCC_CK48CLKSOURCE_PLLQ + + + + + by RCC_CLK48CLKSOURCE_PLLQ
      • +
      +
    • Update HAL_RCCEx_GetPeriphCLKConfig() + and HAL_RCCEx_PeriphCLKConfig() + + + + + functions to support TIM Prescaler + for STM32F411xx devices
    • +
    • HAL_RCCEx_PeriphCLKConfig() API: update + to fix the RTC clock + configuration issue
    • +
    +
  • HAL + + + + CEC update
  • +
      +
    • Overall + driver rework with break + of compatibility with HAL + V1.4.4
    • +
        +
      • Remove the + HAL CEC polling Process: HAL_CEC_Transmit() + and HAL_CEC_Receive()
      • +
      +
    +
+
    +
      +
        +
      • Remove the + HAL CEC receive interrupt + process (HAL_CEC_Receive_IT()) + + + + + and manage the "Receive" + mode enable within the Init + phase
      • +
      • Rename HAL_CEC_GetReceivedFrameSize() + function to HAL_CEC_GetLastReceivedFrameSize() + + + + + function
      • +
      • Add new HAL + APIs: HAL_CEC_SetDeviceAddress() + and HAL_CEC_ChangeRxBuffer()
      • +
      • Remove + the 'InitiatorAddress' + field from the CEC_InitTypeDef + structure and manage + it as a parameter in + the HAL_CEC_Transmit_IT() + function
      • +
      • Add new + parameter 'RxFrameSize' + in HAL_CEC_RxCpltCallback() + function
      • +
      • Move CEC Rx + buffer pointer from CEC_HandleTypeDef + structure to CEC_InitTypeDef + structure
      • +
      +
    • Update driver + to implement the new CEC state + machine:
    • +
        +
      • Add + new "rxState" field + + + + + in CEC_HandleTypeDef + structure to provide the CEC state + + + + + information related to Rx Operations
      • +
      • Rename + "state" field in CEC_HandleTypeDef + structure to "gstate": + + + + CEC state + + + + + information related to + global Handle management and + Tx Operations
      • +
      • Update CEC + process to manage the new + CEC states.
      • +
      • Update + __HAL_CEC_RESET_HANDLE_STATE() + macro to handle the new CEC + state parameters (gState, + rxState)
      • +
      +
    +
+
    +
  • HAL + + + + UART, USART, SMARTCARD and + IRDA (referenced + + + + as PPP here below) update
  • +
      +
    • Update + Polling management:
    • +
        +
      • The user + Timeout value must be + estimated for the overall + process duration: the + Timeout measurement is + cumulative
      • +
      +
    • Update DMA + process:
    • +
        +
      • Update the + management of PPP peripheral + errors during DMA process. + This requires the following + updates in user application:
      • +
          +
        • Configure + and enable the PPP IRQ in + HAL_PPP_MspInit() + function
        • +
        • In + stm32f4xx_it.c file, PPP_IRQHandler() + function: add a call to HAL_PPP_IRQHandler() + + + + + function
        • +
        • Add and + customize the Error + Callback API: HAL_PPP_ErrorCallback()
        • +
        +
      +
    +
  • HAL + + + + FMC update
  • +
      +
    • Update FMC_NORSRAM_Init() + to remove the Burst access + mode configuration
    • +
    • Update FMC_SDRAM_Timing_Init() + to fix initialization issue + when configuring 2 SDRAM banks
    • +
    +
  • HAL + + + + HCD update
  • +
      +
    • Update HCD_Port_IRQHandler() + to unmask disconnect IT only + when the port is disabled
    • +
    +
  • HAL + + + + I2C/FMPI2C + update
  • +
      +
    • Update Polling + + + + + management:
    • +
        +
      • The Timeout + value must be estimated for + the overall process + duration: the + Timeout measurement is + cumulative
      • +
      +
    • Add the + management of Abort + service: Abort DMA + transfer through interrupt
    • +
        +
      • In the case + of Master Abort IT transfer + usage:
      • +
          +
        • Add new + + + + user HAL_I2C_AbortCpltCallback() + to inform user of the end + of abort process
        • +
        • A new + abort state is defined in + the HAL_I2C_StateTypeDef structure
        • +
        +
      +
    • Add the + management of I2C peripheral + errors, ACK failure and STOP + condition detection during DMA + process. This requires the + following updates on user + application:
    • +
        +
      • Configure + and enable the I2C IRQ in + HAL_I2C_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, I2C_IRQHandler() + function: add a call to + HAL_I2C_IRQHandler() + function
      • +
      • Add and + customize the Error Callback + API: HAL_I2C_ErrorCallback()
      • +
      • Refer to + the I2C_EEPROM or + I2C_TwoBoards_ComDMA project + examples usage of the API
      • +
      +
    • NACK error + during addressing phase is + returned through interrupt + instead of previously through + I2C transfer API's
    • +
    • I2C + addressing phase is updated to + be managed using interrupt + instead of polling (Only + for HAL I2C driver)
    • +
        +
      • Add new + static functions to manage + I2C SB, ADDR and ADD10 flags
      • +
      +
    +
  • HAL + + + + SPI update
  • +
+
    +
      +
    • Overall + driver optimization to improve + performance in + polling/interrupt mode to + reach maximum peripheral frequency
    • +
        +
      • Polling + mode:
      • +
          +
        • Replace + the use of SPI_WaitOnFlagUnitTimeout() + function by "if" statement + to check on RXNE/TXE flage + while transferring data
        • +
        +
      +
    +
+
    +
      +
        +
      •  Interrupt + + + + mode:
      • +
          +
        • Minimize + access on SPI registers
        • +
        +
      • All modes:
      • +
          +
        • Add the + USE_SPI_CRC switch to + minimize the number of + statements when CRC + calculation is disabled
        • +
        • Update timeout + + + + + management to check on + global processes
        • +
        • Update + error code management in + all processes
        • +
        +
      +
    • Update DMA + process:
    • +
        +
      • Add the + management of SPI peripheral + errors during DMA process. + This requires the following + updates in the user + application:
      • +
          +
        • Configure + and enable the SPI IRQ in + HAL_SPI_MspInit() + function
        • +
        • In + stm32f4xx_it.c file, SPI_IRQHandler() + function: add a call to HAL_SPI_IRQHandler() + + + + + function
        • +
        • Add and + customize the Error + Callback API: HAL_SPI_ErrorCallback()
        • +
        • Refer to + the following example + which describe the + changes: SPI_FullDuplex_ComDMA
        • +
        +
      +
    • Fix + regression in polling mode:
    • +
        +
      • Add + preparing data to transmit + in case of slave mode in HAL_SPI_TransmitReceive() + and HAL_SPI_Transmit()
      • +
      • Add to + manage properly the overrun + flag at the end of a HAL_SPI_TransmitReceive()
      • +
      +
    • Fix + regression in interrupt mode:
    • +
        +
      • Add a wait + on TXE flag in SPI_CloseTx_ISR() + and in SPI_CloseTxRx_ISR()
      • +
      • Add to + manage properly + the overrun flag in SPI_CloseRxTx_ISR() + and SPI_CloseRx_ISR()
      • +
      +
    +
+
    +
  • HAL + + + + DMA2D update
  • +
      +
    • Update the + HAL_DMA2D_DeInit() + function to:
    • +
        +
      • Abort + transfer in case of ongoing + DMA2D transfer
      • +
      • Reset DMA2D + control registers
      • +
      +
    • Update + HAL_DMA2D_Abort() + to disable DMA2D interrupts + after stopping transfer
    • +
    • Optimize + HAL_DMA2D_IRQHandler() + by reading status registers + only once
    • +
    • Update + HAL_DMA2D_ProgramLineEvent() + function to:
    • +
        +
      • Return HAL + error state in case of wrong + line value
      • +
      • Enable line + interrupt after setting the + line watermark configuration
      • +
      +
    • Add new + HAL_DMA2D_CLUTLoad() + and HAL_DMA2D_CLUTLoad_IT() functions + + + + + to start DMA2D CLUT loading
    • +
        +
      • HAL_DMA2D_CLUTLoading_Abort() + function to abort the DMA2D + CLUT loading
      • +
      • HAL_DMA2D_CLUTLoading_Suspend() + function to suspend the + DMA2D CLUT loading
      • +
      • HAL_DMA2D_CLUTLoading_Resume() + function to resume the DMA2D + CLUT loading
      • +
      +
    • Add new DMA2D + dead time management:
    • +
        +
      • HAL_DMA2D_EnableDeadTime() + function to enable DMA2D + dead time feature
      • +
      • HAL_DMA2D_DisableDeadTime() + function to disable DMA2D + dead time feature
      • +
      • HAL_DMA2D_ConfigDeadTime() + function to configure dead + time
      • +
      +
    • Update the + name of DMA2D Input/Output + color mode defines to be more + + + + clear for + user (DMA2D_INPUT_XXX for + input layers Colors, + DMA2D_OUTPUT_XXX for output + framebuffer Colors)
    • +
    +
+
    +
  • HAL + + + + LTDC update
  • +
+
    +
      +
    • Update HAL_LTDC_IRQHandler() + to manage the case of reload + interrupt
    • +
    • Add new + callback API HAL_LTDC_ReloadEventCallback()
    • +
    • Add HAL_LTDC_Reload() + to configure LTDC reload + feature
    • +
    • Add new No + Reload LTDC variant APIs
    • +
        +
      • HAL_LTDC_ConfigLayer_NoReload() to + configure the LTDC Layer + according to the specified + without reloading
      • +
      • HAL_LTDC_SetWindowSize_NoReload() to set + the LTDC window size without + reloading
      • +
      • HAL_LTDC_SetWindowPosition_NoReload() to set + the LTDC window position + without reloading
      • +
      • HAL_LTDC_SetPixelFormat_NoReload() to + reconfigure the pixel format + without reloading
      • +
      • HAL_LTDC_SetAlpha_NoReload() to + reconfigure the layer alpha + value without reloading
      • +
      • HAL_LTDC_SetAddress_NoReload() to + reconfigure the frame buffer + Address without reloading
      • +
      • HAL_LTDC_SetPitch_NoReload() to + reconfigure the pitch for + specific cases
      • +
      • HAL_LTDC_ConfigColorKeying_NoReload() to + configure the color keying + without reloading
      • +
      • HAL_LTDC_EnableColorKeying_NoReload() to enable + the color keying without + reloading
      • +
      • HAL_LTDC_DisableColorKeying_NoReload() to + disable the color keying + without reloading
      • +
      • HAL_LTDC_EnableCLUT_NoReload() to enable + the color lookup table + without reloading
      • +
      • HAL_LTDC_DisableCLUT_NoReload() to + disable the color lookup + table without reloading
      • +
      • Note: Variant + functions with “_NoReload” + post fix allows to set the + LTDC configuration/settings + without immediate reload. + This is useful in case when + the program requires to + modify several LTDC settings + (on one or both layers) then + applying (reload) these + settings in one shot by + calling the function “HAL_LTDC_Reload
      • +
      +
    +
  • HAL + + + + RTC update 
  • +
      +
    • Add new + timeout implementation based + on cpu + cycles + for ALRAWF, ALRBWF + and WUTWF flags
    • +
    +
+
    +
  • HAL + + + + SAI update
  • +
      +
    • Update SAI + state in case of TIMEOUT error + within the HAL_SAI_Transmit() + / HAL_SAI_Receive()
    • +
    • Update HAL_SAI_IRQHandler:
    • +
        +
      • Add error + management in case DMA + errors through XferAbortCallback() + and HAL_DMA_Abort_IT()
      • +
      • Add error + management in case of IT
      • +
      +
    • Move SAI_BlockSynchroConfig() + and SAI_GetInputClock() + + + + + functions to + stm32f4xx_hal_sai.c/.h files + (extension files are kept + empty for projects + compatibility reason)
    • +
    +
+
    +
  • HAL + + + + DCMI update
  • +
      +
    • Rename DCMI_DMAConvCplt + to DCMI_DMAXferCplt
    • +
    • Update HAL_DCMI_Start_DMA() + function to Enable the + DCMI peripheral
    • +
    • Add new + timeout implementation based + on cpu + cycles for DCMI stop
    • +
    • Add HAL_DCMI_Suspend() + function to suspend DCMI + capture
    • +
    • Add HAL_DCMI_Resume() + function to resume capture + after DCMI suspend
    • +
    • Update lock + mechanism for DCMI process
    • +
    • Update HAL_DCMI_IRQHandler() + function to:
    • +
        +
      • Add error + management in case DMA + errors through XferAbortCallback() + and HAL_DMA_Abort_IT()
      • +
      • Optimize + code by using direct + register read
      • +
      +
    +
+
    +
  • HAL + + + + DMA + update
  • +
      +
    • Add new APIs + HAL_DMA_RegisterCallback() + and HAL_DMA_UnRegisterCallback + to register/unregister the + different callbacks identified + by the enum + typedef HAL_DMA_CallbackIDTypeDef
    • +
    • Add new API HAL_DMA_Abort_IT() + to abort DMA transfer under + interrupt context
    • +
        +
      • The new + registered Abort callback is + called when DMA transfer + abortion is completed
      • +
      +
    • Add the check + of compatibility between FIFO + threshold level and size of + the memory burst in the HAL_DMA_Init() + API
    • +
    • Add new Error + Codes: HAL_DMA_ERROR_PARAM, + HAL_DMA_ERROR_NO_XFER and + HAL_DMA_ERROR_NOT_SUPPORTED
    • +
    • Remove all + DMA states related to + MEM0/MEM1 in HAL_DMA_StateTypeDef
    • +
    +
  • HAL + + + + IWDG + update
  • +
      +
    • Overall + rework of the driver for a + more + efficient implementation
    • +
        +
      • Remove the + following APIs:
      • +
          +
        • HAL_IWDG_Start()
        • +
        • HAL_IWDG_MspInit()
        • +
        • HAL_IWDG_GetState()
        • +
        +
      • Update + implementation:
      • +
          +
        • HAL_IWDG_Init(): this + function insures the + configuration and the + start of the IWDG counter
        • +
        • HAL_IWDG_Refresh(): this + function insures the + reload of the IWDG counter
        • +
        +
      • Refer to + the following example to + identify the changes: IWDG_Example
      • +
      +
    +
  • HAL + + + + LPTIM + update
  • +
      +
    • Update HAL_LPTIM_TimeOut_Start_IT() + and HAL_LPTIM_Counter_Start_IT( + ) APIs to configure WakeUp + Timer EXTI interrupt to be + able to wakeup + MCU from low power mode by + pressing the EXTI line.
    • +
    • Update HAL_LPTIM_TimeOut_Stop_IT() + and HAL_LPTIM_Counter_Stop_IT( + ) APIs to disable WakeUp + Timer EXTI interrupt. 
    • +
    +
  • HAL + + + + NOR update
  • +
      +
    • Update + NOR_ADDR_SHIFT macro implementation
    • +
    +
  • HAL + + + + PCD update
  • +
      +
    • Update HAL_PCD_IRQHandler() + to get HCLK frequency before + setting TRDT value
    • +
    +
  • HAL + + + + QSPI + update
  • +
+
    +
      +
    • Update to + manage QSPI error management + during DMA process
    • +
    • Improve the + DMA transmit process by using + QSPI TC interrupt instead of + waiting loop on TC flag under + DMA ISR
    • +
    • These two + improvements require the + following updates on user + application:
    • +
        +
      • Configure + and enable the QSPI IRQ in HAL_QSPI_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, QSPI_IRQHandler() + function: add a call to HAL_QSPI_IRQHandler() + + + + function
      • +
      • Add and + customize the Error Callback + API: HAL_QSPI_ErrorCallback()
      • +
      +
    • Add the + management of non-blocking + transfer abort service: HAL_QSPI_Abort_IT(). + + + + + In this case the user must:
    • +
        +
      • Add new + callback HAL_QSPI_AbortCpltCallback() + to inform user at the end of + abort process
      • +
      • A new value + of State in the HAL_QSPI_StateTypeDef + provides the current state + during the abort phase
      • +
      +
    • Polling + management update:
    • +
        +
      • The Timeout + value user must be estimated + for the overall process + duration: the + Timeout measurement is + cumulative. 
      • +
      +
    • Refer to the + following examples, which + describe the changes:
    • +
        +
      • QSPI_ReadWrite_DMA
      • +
      • QSPI_MemoryMapped
      • +
      • QSPI_ExecuteInPlace
      • +
      +
    +
+
    +
      +
    • Add two new + APIs for the QSPI fifo + threshold:
    • +
        +
      • HAL_QSPI_SetFifoThreshold(): + configure the FIFO threshold + of the QSPI
      • +
      • HAL_QSPI_GetFifoThreshold(): give the + current FIFO threshold
      • +
      +
    • Fix wrong + data size management in HAL_QSPI_Receive_DMA()
    • +
    +
+
    +
  • HAL + + + + ADC update
  • +
      +
    • Add new + __HAL_ADC_PATH_INTERNAL_VBAT_DISABLE() + macro for STM32F42x and + STM32F43x devices to + provide the possibility + to convert VrefInt + channel when both VrefInt + and Vbat + channels are selected.
    • +
    +
  • HAL + + + + SPDIFRX update
  • +
      +
    • Overall driver + update for wait on flag + management optimization 
    • +
    +
  • HAL + + + + WWDG update 
  • +
      +
    • Overall + rework of the driver for more + efficient implementation
    • +
        +
      • Remove the + following APIs:
      • +
          +
        • HAL_WWDG_Start()
        • +
        • HAL_WWDG_Start_IT()
        • +
        • HAL_WWDG_MspDeInit()
        • +
        • HAL_WWDG_GetState()
        • +
        +
      • Update + implementation:
      • +
          +
        • HAL_WWDG_Init()
        • +
            +
          • A new + + + + parameter in the Init + Structure: EWIMode
          • +
          +
        • HAL_WWDG_MspInit()
        • +
        • HAL_WWDG_Refresh(
        • +
            +
          • This + function insures the + reload of the counter
          • +
          • The + "counter" parameter has + been removed
          • +
          +
        • HAL_WWDG_IRQHandler()
        • +
        • HAL_WWDG_EarlyWakeupCallback() is the + new prototype of HAL_WWDG_WakeUpCallback()
        • +
        +
      +
    • Refer to the + following example to identify + the changes: WWDG_Example
    • +
    +
+

V1.4.4 + + + + / 22-January-2016

+

Main Changes

+
    +
  • HAL + + + + Generic update
  • +
      +
    • stm32f4xx_hal_conf_template.h
    • +
        +
      • Optimize + HSE Startup Timeout value + from 5000ms to 100 ms
      • +
      • Add new + define LSE_STARTUP_TIMEOUT
      • +
      • Add new + define USE_SPI_CRC for code + cleanup when the CRC + calculation is disabled.
      • +
      +
    • Update HAL + drivers to support MISRA C + 2004 rule 10.6
    • +
    • Add new + template driver to + configure timebase + using TIMER :
    • +
        +
      • stm32f4xx_hal_timebase_tim_template.c
      • +
      +
    +
+
    +
  • HAL + + + + CAN update
  • +
      +
    • Update HAL_CAN_Transmit() + and HAL_CAN_Transmit_IT() + + + + + functions to unlock + process when all Mailboxes are + busy
    • +
    +
+
    +
  • HAL + + + + DSI update
  • +
      +
    • Update HAL_DSI_SetPHYTimings() + functions to use the correct + mask
    • +
    +
  • HAL + + + + UART update
  • +
      +
    • Several + update on HAL UART driver to + implement the new UART state + machine: 
    • +
        +
      • Add new + field in UART_HandleTypeDef + structure: "rxState", + + + + + UART state information + related to Rx Operations
      • +
      • Rename + "state" field in UART_HandleTypeDef + structure by "gstate": + + + + UART state information + related to global Handle + management and Tx Operations
      • +
      • Update UART + process to manage the new + UART states.
      • +
      • Update + __HAL_UART_RESET_HANDLE_STATE() + macro to handle the new UART + state parameters (gState, + rxState)
      • +
      +
    • Update + UART_BRR_SAMPLING16() and + UART_BRR_SAMPLING8() Macros to + fix wrong baudrate + calculation.
    • +
    +
+
    +
  • HAL + + + + IRDA update
  • +
      +
    • Several + update on HAL IRDA driver to + implement the new UART state + machine: 
    • +
        +
      • Add new + field in IRDA_HandleTypeDef + structure: "rxState", + + + + + IRDA state information + related to Rx Operations
      • +
      • Rename + "state" field in UART_HandleTypeDef + structure by "gstate": + + + + IRDA state information + related to global Handle + management and Tx Operations
      • +
      • Update IRDA + process to manage the new + UART states.
      • +
      • Update + __HAL_IRDA_RESET_HANDLE_STATE() + macro to handle the new IRDA + state parameters (gState, + rxState)
      • +
      +
    • Removal of + IRDA_TIMEOUT_VALUE define
    • +
    • Update IRDA_BRR() + Macro to fix wrong baudrate + calculation
    • +
    +
  • HAL + + + + SMARTCARD update
  • +
      +
    • Several + update on HAL SMARTCARD driver + to implement the new UART + state machine: 
    • +
        +
      • Add new + field in SMARTCARD_HandleTypeDef + structure: "rxState", + + + + + SMARTCARDstate + information related to Rx Operations
      • +
      • Rename + "state" field in UART_HandleTypeDef + structure by "gstate": + + + + SMARTCARDstate + information related to + global Handle management and + Tx Operations
      • +
      • Update SMARTCARD + + + + + process to manage the new + UART states.
      • +
      • Update + __HAL_SMARTCARD_RESET_HANDLE_STATE() + macro to handle the + new SMARTCARD state + parameters (gState, + rxState)
      • +
      +
    • Update + SMARTCARD_BRR() + macro to fix wrong baudrate + calculation
    • +
    +
+
    +
  • HAL  + RCC + update
  • +
      +
    • Add new + default define value for HSI + calibration + "RCC_HSICALIBRATION_DEFAULT"
    • +
    • Optimize + Internal oscillators and PLL + startup timeout 
    • +
    • Update to + avoid the disable for HSE/LSE + oscillators before setting the + new RCC HSE/LSE configuration + and add the following notes in + HAL_RCC_OscConfig() + API description:
    • +
    +
+

     + + + +       +     +     +     +       * + @note   Transitions LSE + Bypass to LSE On and LSE On to LSE + Bypass are not
+
    + + + + +     +     +     +     +     +      + *         +     supported by this + API. User should request a + transition to LSE Off
+
    + + + + +     +     +     +     +     +      + *         +     first and then LSE + On or LSE Bypass.
+
    + + + + +     +     +     +     +     +      * + @note   Transition HSE + Bypass to HSE On and HSE On to HSE + Bypass are not
+
    + + + + +     +     +     +     +     +      + *         +     supported by this + API. User should request a + transition to HSE Off
+
    + + + + +     +     +     +         +      + *         +     first and then HSE + On or HSE Bypass.

+
    +
      +
    • Optimize + the HAL_RCC_ClockConfig() + API implementation.
    • +
    +
+
    +
  • HAL + + + + DMA2D update
  • +
      +
    • Update + HAL_DMA2D_Abort() + Function to end current DMA2D + transfer properly
    • +
    • Update + HAL_DMA2D_PollForTransfer() + function to add poll for + background CLUT loading (layer + 0 and layer 1).
    • +
    • Update + HAL_DMA2D_PollForTransfer() + to set the corresponding ErrorCode + in case of error occurrence
    • +
    • Update + HAL_DMA2D_ConfigCLUT() + function to fix wrong CLUT + size and color mode settings
    • +
    • Removal of + useless macro __HAL_DMA2D_DISABLE()
    • +
    • Update + HAL_DMA2D_Suspend() + to manage correctly the case + where no transfer is on going
    • +
    • Update + HAL_DMA2D_Resume() to + + + + + manage correctly the case + where no transfer is on going
    • +
    • Update + HAL_DMA2D_Start_IT() + to enable all required + interrupts before enabling the + transfer.
    • +
    • Add + HAL_DMA2D_CLUTLoad_IT() + Function to allow loading a + CLUT with interruption model.
    • +
    •  Update + HAL_DMA2D_IRQHandler() + to manage the following + cases :
      +
      +
    • +
        +
      • CLUT + transfer complete
      • +
      • CLUT access + error
      • +
      • Transfer + watermark reached
      • +
      +
    • Add new + Callback APIs:
    • +
        +
      •  HAL_DMA2D_LineEventCallback() + to signal a transfer + watermark reached event
      • +
      •  HAL_DMA2D_CLUTLoadingCpltCallback() + to signal a CLUT loading + complete event
      • +
      +
    +
+
    +
      +
    • Miscellaneous + Improvement:
    • +
        +
      • Add + "HAL_DMA2D_ERROR_CAE" new + define for CLUT Access error + management.
      • +
      • Add     assert_param” + used for parameters check is + now done on the top of the + exported functions : before + locking the process using + __HAL_LOCK
      • +
      +
    +
+

 

+
    +
  • HAL + + + + I2C update
  • +
      +
    • Add support + of I2C repeated start feature:
    • +
        +
      • With the + following new API's
      • +
          +
        • HAL_I2C_Master_Sequential_Transmit_IT()
        • +
        • HAL_I2C_Master_Sequential_Receive_IT()
        • +
        • HAL_I2C_Master_Abort_IT()
        • +
        • HAL_I2C_Slave_Sequential_Transmit_IT()
        • +
        • HAL_I2C_Slave_Sequential_Receive_IT()
        • +
        • HAL_I2C_EnableListen_IT()
        • +
        • HAL_I2C_DisableListen_IT()
        • +
        +
      • Add new + user callbacks:
      • +
          +
        • HAL_I2C_ListenCpltCallback()
        • +
        • HAL_I2C_AddrCallback()
        • +
        +
      +
    • Update to + generate STOP condition when a + acknowledge failure error is detected
    • +
    • Several + update on HAL I2C driver to + implement the new I2C state + machine: 
    • +
        +
      • Add new API + to get the I2C mode: + HAL_I2C_GetMode()
      • +
      • Update I2C + process to manage the new + I2C states.
      • +
      +
    • Fix wrong behaviour + in single byte transmission 
    • +
    • Update I2C_WaitOnFlagUntilTimeout() to + + + + + manage the NACK feature.
    • +
    • Update  I2C + transmission process to + support the case data size + equal 0
    • +
    +
+
    +
  • HAL + + + + FMPI2C update
  • +
      +
    • Add support + of FMPI2C repeated start + feature:
    • +
        +
      • With the + following new API's
      • +
          +
        • HAL_FMPI2C_Master_Sequential_Transmit_IT()
        • +
        • HAL_FMPI2C_Master_Sequential_Receive_IT()
        • +
        • HAL_FMPI2C_Master_Abort_IT()
        • +
        • HAL_FMPI2C_Slave_Sequential_Transmit_IT()
        • +
        • HAL_FMPI2C_Slave_Sequential_Receive_IT()
        • +
        • HAL_FMPI2C_EnableListen_IT()
        • +
        • HAL_FMPI2C_DisableListen_IT()
        • +
        +
      • Add new + user callbacks:
      • +
          +
        • HAL_FMPI2C_ListenCpltCallback()
        • +
        • HAL_FMPI2C_AddrCallback()
        • +
        +
      +
    • Several + update on HAL I2C driver to + implement the new I2C state + machine: 
    • +
        +
      • Add new API + to get the FMPI2C mode: + HAL_FMPI2C_GetMode()
      • +
      • Update + FMPI2C process to manage the + new FMPI2C states.
      • +
      +
    +
+
    +
  • HAL + + + + SPI update
  • +
      +
    • Major Update + to improve performance in + polling/interrupt mode to + reach max frequency:
    • +
        +
      • Polling mode + + + + :
      • +
          +
        • Replace + use of SPI_WaitOnFlagUnitTimeout() + funnction + by "if" statement to check + on RXNE/TXE flage + while transferring data.
        • +
        • Use API + data pointer instead of + SPI handle data pointer.
        • +
        • Use a Goto + implementation instead of + "if..else" + statements.
        • +
        +
      +
    +
+
    +
      +
        +
      • Interrupt + mode
      • +
          +
        • Minimize + access on SPI registers.
        • +
        • Split the + SPI modes into dedicated + static functions to + minimize checking + statements under HAL_IRQHandler():
        • +
            +
          • 1lines/2lines + + + + modes
          • +
          • 8 bit/ + 16 bits data formats
          • +
          • CRC + calculation + enabled/disabled.
          • +
          +
        • Remove + waiting loop under ISR + when closing + + + +  the + communication.
        • +
        +
      • All + modes:  
      • +
          +
        • Adding + switch USE_SPI_CRC to + minimize number of + statements when CRC + calculation is disabled.
        • +
        • Update + Timeout management to + check on global process.
        • +
        • Update + Error code management in + all processes.
        • +
        +
      +
    • Add note to + the max frequencies reached in + all modes.
    • +
    • Add note + about Master Receive mode restrictions :
    • +
        +
      • Master + + + + Receive mode restriction:
        +       + (#) In Master + unidirectional receive-only + mode (MSTR =1, BIDIMODE=0, + RXONLY=0) or
        +           + + + + + bidirectional receive mode + (MSTR=1, BIDIMODE=1, + BIDIOE=0), to ensure that + the SPI
        +           + + + + does not initiate a new + transfer the following + procedure has to be + respected:
        +           + + + + (##) HAL_SPI_DeInit()
        +           + + + + (##) HAL_SPI_Init() + + + +
      • +
      +
    +
+
    +
  • HAL + + + + SAI update
  • +
      +
    • Update for + proper management of the + external synchronization input + selection
    • +
        +
      • update + of HAL_SAI_Init + () funciton
      • +
      • update + definition of SAI_Block_SyncExt + and SAI_Block_Synchronization + groups
      • +
      +
    • Update + SAI_SLOTACTIVE_X +  defines + values
    • +
    • Update HAL_SAI_Init() + function for proper companding + mode management
    • +
    • Update SAI_Transmit_ITxxBit() + functions to add the check on + transfer counter before + writing new data to SAIx_DR + registers
    • +
    • Update SAI_FillFifo() + function to avoid issue when + the number of data to transmit + is smaller than the FIFO size
    • +
    • Update HAL_SAI_EnableRxMuteMode() + function for proper mute + management
    • +
    • Update SAI_InitPCM() + function to support 24bits + configuration
    • +
    +
  • HAL + + + + ETH update
  • +
      +
    • Removal of + ETH MAC debug register defines
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • Update FLASH_MassErase() + function to apply correctly + voltage range parameter
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Update I2S_DMATxCplt() + and I2S_DMARxCplt() to manage + properly FullDuplex + mode without any risk of + missing data.
    • +
    +
  • LL + + + + FMC update
  • +
      +
    • Update the FMC_NORSRAM_Init() + function to use BurstAccessMode + field properly
    • +
    +
  • LL + + + + FSMC  + + + + update
  • +
      +
    • Update the FSMC_NORSRAM_Init() + function to use BurstAccessMode + field properly
    • +
    +
+


+
+

+

V1.4.4 + / 11-December-2015

+

Main Changes

+
    +
  • HAL + + + + Generic update
  • +
      +
    • Update HAL + weak empty callbacks to + prevent unused argument + compilation warnings with some + compilers by calling the + following line:
    • +
        +
      • UNUSED(hppp);
      • +
      +
    • STM32Fxxx_User_Manual.chm + + + + + files regenerated for HAL + V1.4.3
    • +
    +
  • HAL + + + + ETH update 
  • +
      +
    • Update HAL_ETH_Init() + function to add timeout on the + Software reset management
    • +
    +
+

V1.4.2 + + + + / 10-November-2015

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • One + + + + change done on the HAL CRYP + requires an update on the + application code based on HAL + V1.4.1
  • +
      +
    • Update HAL_CRYP_DESECB_Decrypt() + API to invert pPlainData + and pCypherData + parameters
    • +
    +
  • HAL + + + + generic + update
  • +
      +
    • Update HAL + weak empty callbacks to + prevent unused argument + compilation warnings with some + compilers by calling the + following line:
    • +
        +
      • UNUSED(hppp);
      • +
      +
    +
+
    +
  • HAL + + + + CORTEX update
  • +
      +
    • Remove + duplication for + __HAL_CORTEX_SYSTICKCLK_CONFIG() + macro
    • +
    +
+
    +
  • HAL + + + + HASH update
  • +
      +
    • Rename HAL_HASH_STATETypeDef + to HAL_HASH_StateTypeDef
    • +
    • Rename HAL_HASH_PhaseTypeDef + to HAL_HASH_PhaseTypeDef
    • +
    +
  • HAL + + + + RCC update
  • +
      +
    • Add new + macros __HAL_RCC_PPP_IS_CLK_ENABLED() + to check on Clock + enable/disable status
    • +
    • Update + __HAL_RCC_USB_OTG_FS_CLK_DISABLE() + macro to remove the disable + for the SYSCFG
    • +
    • Update HAL_RCC_MCOConfig() + API to use new defines for the + GPIO Speed
    • +
    • Generic + update to improve the + PLL VCO min + value(100MHz): PLLN, PLLI2S + and PLLSAI min value is 50 + instead of 192
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • __HAL_FLASH_INSTRUCTION_CACHE_RESET() + macro: update to reset +  ICRST bit in + the ACR register after + setting it.
    • +
    • Update to + support until 15 FLASH wait + state (FLASH_LATENCY_15) for + STM32F446xx devices +
    • +
    +
+

§  + + + + + HAL CRYP update

+
    +
      +
    • Update HAL_CRYP_DESECB_Decrypt() + API to fix the inverted pPlainData + and pCypherData + parameters issue
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Update + HAL_I2S_Init() + API to call + __HAL_RCC_I2S_CONFIG() macro + when external I2S clock is + selected
    • +
    +
  • HAL + + + + LTDC update
  • +
      +
    • Update HAL_LTDC_SetWindowPosition() + API to configure + Immediate reload register + instead of vertical blanking + reload register.
    • +
    +
  • HAL + + + + TIM update
  • +
      +
    • Update HAL_TIM_ConfigClockSource() + API to check only the + required parameters
    • +
    +
  • HAL + + + + NAND update
  • +
      +
    • Update + HAL_NAND_Read_Page()/HAL_NAND_Write_Page()/HAL_NAND_Read_SpareArea() + APIs to manage correctly the + NAND Page access
    • +
    +
  • HAL + + + + CAN update
  • +
      +
    • Update to use + "=" instead of "|=" to clear + flags in the MSR, TSR, RF0R + and RF1R registers
    • +
    +
  • HAL + + + + HCD update
  • +
      +
    • Fix typo in + __HAL_USB_OTG_HS_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE() + macro implementation
    • +
    +
  • HAL + + + + PCD update
  • +
      +
    • Update HAL_PCD_IRQHandler() + API to avoid issue + when DMA mode enabled for + Status Phase IN stage
    • +
    +
  • LL + + + + FMC update
  • +
      +
    • Update the FMC_NORSRAM_Extended_Timing_Init() + API to remove the check + on CLKDIvison + and DataLatency + parameters
    • +
    • Update the FMC_NORSRAM_Init() + API to add a check on the PageSize + parameter for STM32F42/43xx + devices
    • +
    +
  • LL + + + + FSMC update
  • +
      +
    • Update the FSMC_NORSRAM_Extended_Timing_Init() + API to remove the check + on CLKDIvison + and DataLatency + parameters
    • +
    +
+

V1.4.1 + + + + / 09-October-2015

+

Main Changes

+
    +
  • HAL + + + + DSI update
  • +
      +
    • Update TCCR + register assigned value + in HAL_DSI_ConfigHostTimeouts() + function
    • +
    • Update WPCR + register assigned value + in HAL_DSI_Init(), + + + + + HAL_DSI_SetSlewRateAndDelayTuning(), + + + + + HAL_DSI_SetSlewRateAndDelayTuning(), + + + + + HAL_DSI_SetLowPowerRXFilter() + + + + + / HAL_DSI_SetSDD(), + + + + + HAL_DSI_SetLanePinsConfiguration(), + + + + + HAL_DSI_SetPHYTimings(), + + + + + HAL_DSI_ForceTXStopMode(), + + + + + HAL_DSI_ForceRXLowPower(), + + + + + HAL_DSI_ForceDataLanesInRX(), + + + + + HAL_DSI_SetPullDown() + + + + + and HAL_DSI_SetContentionDetectionOff() + + + + + functions
    • +
    • Update + DSI_HS_PM_ENABLE define value
    • +
    • Implement + workaround for the hardware + limitation: “The time to + activate the clock between HS + transmissions is not + calculated correctly”
    • +
    +
+

V1.4.0 + + + + / 14-August-2015

+

Main Changes

+
    +
  • Add + support of STM32F469xx, STM32F479xx, + STM32F410Cx, STM32F410Rx + and STM32F410Tx  + devices
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Add + new HAL drivers for DSI and LPTIM + + + + + peripherals
  • +
+
    +
  • HAL + + + + ADC update
  • +
      +
    • Rename + ADC_CLOCKPRESCALER_PCLK_DIV2 + define to + ADC_CLOCK_SYNC_PCLK_DIV2
    • +
    • Rename + ADC_CLOCKPRESCALER_PCLK_DIV4 + define to + ADC_CLOCK_SYNC_PCLK_DIV4
    • +
    • Rename + ADC_CLOCKPRESCALER_PCLK_DIV6 + define to + ADC_CLOCK_SYNC_PCLK_DIV6
    • +
    • Rename + ADC_CLOCKPRESCALER_PCLK_DIV8 + define to + ADC_CLOCK_SYNC_PCLK_DIV8
    • +
    +
  • HAL + + + + CORTEX update
  • +
      +
    • Add specific + API for MPU management
    • +
        +
      • add MPU_Region_InitTypeDef + structure
      • +
      • add new + function HAL_MPU_ConfigRegion()
      • +
      +
    +
  • HAL + + + + DMA update
  • +
      +
    • Overall driver + update for code optimization
    • +
        +
      • add StreamBaseAddress + and StreamIndex + new fields in the DMA_HandleTypeDef + structure
      • +
      • add DMA_Base_Registers + private structure
      • +
      • add static + function DMA_CalcBaseAndBitshift()
      • +
      • update HAL_DMA_Init() + function to use the new + added static function
      • +
      • update HAL_DMA_DeInit() + function to optimize clear + flag operations
      • +
      • update HAL_DMA_Start_IT() + function to optimize + interrupts enable
      • +
      • update HAL_DMA_PollForTransfer() + function to optimize check + on flags
      • +
      • update HAL_DMA_IRQHandler() + function to optimize + interrupt flag management
      • +
      +
    +
  • HAL + + + + FLASH update
  • +
      +
    • update HAL_FLASH_Program_IT() + function by removing the + pending flag clear
    • +
    • update HAL_FLASH_IRQHandler() + function to improve erase + operation procedure
    • +
    • update FLASH_WaitForLastOperation() + function by checking on end of + operation flag
    • +
    +
  • HAL + + + + GPIO update
  • +
      +
    • Rename + GPIO_SPEED_LOW define to + GPIO_SPEED_FREQ_LOW
    • +
    • Rename + GPIO_SPEED_MEDIUM define to + GPIO_SPEED_FREQ_MEDIUM
    • +
    • Rename + GPIO_SPEED_FAST define to + GPIO_SPEED_FREQ_HIGH
    • +
    • Rename + GPIO_SPEED_HIGH define to + GPIO_SPEED_FREQ_VERY_HIGH
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Move + I2S_Clock_Source defines to + extension file to properly add + the support of STM32F410xx devices
    • +
    +
  • HAL + + + + LTDC update
  • +
      +
    • rename HAL_LTDC_LineEvenCallback() + function to HAL_LTDC_LineEventCallback()
    • +
    • add new + function HAL_LTDC_SetPitch()
    • +
    • add new + functions HAL_LTDC_StructInitFromVideoConfig() + and HAL_LTDC_StructInitFromAdaptedCommandConfig() + + + + + applicable only to STM32F469xx + and STM32F479xx devices
    • +
    +
  • HAL + + + + PWR update
  • +
      +
    • move + __HAL_PWR_VOLTAGESCALING_CONFIG() + macro to extension file
    • +
    • move + PWR_WAKEUP_PIN2 define to + extension file
    • +
    • add + PWR_WAKEUP_PIN3 define, + applicable only to STM32F10xx + devices
    • +
    • add new + functions HAL_PWREx_EnableWakeUpPinPolarityRisingEdge() + and HAL_PWREx_EnableWakeUpPinPolarityFallingEdge(), + + + + + applicable only to STM32F469xx + and STM32F479xx devices
    • +
    +
+
    +
  • HAL + + + + RTC update
  • +
      +
    • Update HAL_RTCEx_SetWakeUpTimer() + and HAL_RTCEx_SetWakeUpTimer_IT() + + + + + functions to properly check on + the WUTWF flag
    • +
    +
  • HAL + + + + TIM update
  • +
      +
    • add new + defines TIM_SYSTEMBREAKINPUT_HARDFAULT,  + + + + TIM_SYSTEMBREAKINPUT_PVD + + + + + and + TIM_SYSTEMBREAKINPUT_HARDFAULT_PVD, + applicable only to STM32F410xx + devices
    • +
    +
+

V1.3.2 + + + + / 26-June-2015

+

Main Changes

+
    +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • One + + + + changes + done on the HAL may require an + update on the application code + based on HAL V1.3.1
  • +
      +
    • HASH IT + process: update to call the HAL_HASH_InCpltCallback() + at the end of the complete + buffer instead of every each + 512 bits
    • +
    +
+
    +
  • HAL + + + + RCC update
  • +
      +
    • HAL_RCCEx_PeriphCLKConfig() updates:
    • +
        +
      • Update the + LSE check condition after + backup domain reset: + update to check LSE + ready flag when LSE + oscillator is already + enabled instead of check on + LSE oscillator only when LSE + is used as RTC clock source
      • +
      • Use the + right macro to check the + PLLI2SQ parameters +
      • +
      +
    +
+
    +
  • HAL + + + + RTC update
  • +
      +
    • __HAL_RTC_TAMPER_TIMESTAMP_EXTI_GET_FLAG() + macro: fix implementation + issue
    • +
    • __HAL_RTC_ALARM_GET_IT(), + + + + + __HAL_RTC_ALARM_CLEAR_FLAG(), + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(), + + + + + __HAL_RTC_TIMESTAMP_CLEAR_FLAG() + + + + and + __HAL_RTC_TAMPER_CLEAR_FLAG() + macros implementation changed: + remove unused cast
    • +
    • IS_RTC_TAMPER() + macro: update to use literal + instead of hardcoded + value 
    • +
    • Add new + parameter SecondFraction + in RTC_TimeTypeDef + structure
    • +
    • HAL_RTC_GetTime() API update + to support the new + parameter SecondFraction +
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • Add new + literal: + ADC_INJECTED_SOFTWARE_START to + be used as possible value for + the ExternalTrigInjecConvEdge + parameter in the ADC_InitTypeDef + structure to select the ADC + software trigger mode.
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • FLASH_OB_GetRDP() API update + to return uint8_t instead of FlagStatus
    • +
    •  __HAL_FLASH_GET_LATENCY() + new macro add to get the flash + latency
    • +
    +
  • HAL + + + + SPI update
  • +
      +
    • Fix the wrong + definition of + HAL_SPI_ERROR_FLAG literal
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • HAL_I2S_Transmit() + API update to check on busy + flag only for I2S slave mode
    • +
    +
  • HAL + + + + CRC update
  • +
      +
    • __HAL_CRC_SET_IDR() + macro implementation change to + use WRITE_REG() instead of + MODIFY_REG()
    • +
    +
  • HAL + + + + DMA2D update
  • +
      +
    • HAL_DMA2D_ConfigLayer() + API update to use "=" instead + of "|=" to erase BGCOLR and + FGCOLR registers before + setting the new configuration
    • +
    +
  • HAL + + + + HASH update
  • +
      +
    • HAL_HASH_MODE_Start_IT() (MODE + + + + stands for MD5, SHA1, + SHA224 and SHA36) updates:
    • +
        +
      • Fix processing + + + + + fail for small input buffers
      • +
      • Update to + unlock the process and + call return + HAL_OK at the end of + HASH processing to avoid + incorrectly repeating software
      • +
      • Update to + properly manage the HashITCounter
      • +
      • Update to + call the HAL_HASH_InCpltCallback() + at the end of the complete + buffer instead of every each + 512 bits
      • +
      +
    • __HAL_HASH_GET_FLAG() + update to  check the + right register when the DINNE + flag  is selected
    • +
    • HAL_HASH_SHA1_Accumulate() + updates:
    • +
        +
      • Add + a call to the new + IS_HASH_SHA1_BUFFER_SIZE() + macro to check the size + parameter. 
      • +
      • Add the + following note in API description
      • +
      +
    +
+
+

 * + + + + + @note  + + + + + Input buffer + size in bytes must be a multiple + of 4 otherwise the digest + computation is corrupted.

+
+
    +
  • HAL + + + + RTC update
  • +
      +
    • Update to + define hardware + independent literals names:
    • +
        +
      • Rename + RTC_TAMPERPIN_PC13 by + + + +  RTC_TAMPERPIN_DEFAULT
      • +
      • Rename + RTC_TAMPERPIN_PA0 by + RTC_TAMPERPIN_POS1
      • +
      • Rename + RTC_TAMPERPIN_PI8 by + RTC_TAMPERPIN_POS1
      • +
      • Rename + RTC_TIMESTAMPPIN_PC13 by + RTC_TIMESTAMPPIN_DEFAULT
      • +
      • Rename + RTC_TIMESTAMPPIN_PA0 by + RTC_TIMESTAMPPIN_POS1
      • +
      • Rename + RTC_TIMESTAMPPIN_PI8 by + RTC_TIMESTAMPPIN_POS1
      • +
      +
    +
  • HAL + + + + ETH update
  • +
      +
    • Remove + duplicated IS_ETH_DUPLEX_MODE() + and IS_ETH_RX_MODE() macros
    • +
    • Remove + illegal space + ETH_MAC_READCONTROLLER_FLUSHING + macro
    • +
    • Update + ETH_MAC_READCONTROLLER_XXX + defined values (XXX can be + IDLE, READING_DATA and + READING_STATUS)
    • +
    +
  • HAL + + + + PCD update
  • +
      +
    • HAL_PCD_IRQHandler API: fix the + bad Configuration of + Turnaround Time
    • +
    +
  • HAL + + + + HCD update
  • +
      +
    • Update to use + local variable in USB + Host channel re-activation
    • +
    +
  • LL + + + + FMC update
  • +
      +
    • FMC_SDRAM_SendCommand() API: remove + the following line: return + HAL_ERROR;
    • +
    +
  • LL + + + + USB update
  • +
      +
    • USB_FlushTxFifo API: + update to flush all Tx FIFO
    • +
    • Update to use + local variable in USB + Host channel re-activation
    • +
    +
+

V1.3.1 + + + + / 25-Mars-2015

+

Main Changes

+
    +
  • HAL + + + + PWR update
  • +
      +
    • Fix + compilation issue with + STM32F417xx product: + update STM32F17xx + by STM32F417xx
    • +
    +
  • HAL + + + + SPI update
  • +
      +
    • Remove unused + variable to avoid warning with + TrueSTUDIO 
    • +
    +
  • HAL + + + + I2C update
  • +
      +
    • I2C + Polling/IT/DMA processes: move + the wait loop on busy + flag at the top of the + processes, to ensure that + software not perform any write + access to I2C_CR1 register + before hardware + clearing STOP bit and to + avoid + + + + + also the + waiting loop on BUSY flag + under I2C/DMA ISR.
    • +
    • Update busy + flag Timeout value
    • +
    • I2C Master + Receive Processes update to + disable ACK before generate + the STOP 
    • +
    +
  • HAL + + + + DAC update
  • +
      +
    • Fix V1.3.0 + regression issue with DAC + software trigger configuration
    • +
    +
+

V1.3.0 + + + + / 09-Mars-2015

+

Main Changes

+
    +
  • Add + support of STM32F446xx devices
  • +
  • General + + + + updates to fix known defects and + enhancements implementation
  • +
  • Add + new HAL drivers for CEC, + QSPI, FMPI2C and SPDIFRX + + + + peripherals
  • +
  • Two + + + + changes done on the HAL + requires an update on the + application code based on HAL + V1.2.0
  • +
      +
    • Overall SAI + driver rework to have + exhaustive support of the + peripheral features: details + are provided in HAL SAI update + + + + section below --> Compatibility + + + + + with previous version is impacted
    • +
    • CRYP driver + updated to support multi instance,so + user must ensure that the + new parameter Instance is + initalized + in his application(CRYPHandle.Instance + = CRYP) 
    • +
    +
+
    +
  • HAL + + + + Generic update
  • +
      +
    • stm32f4xx_hal_def.h
    • +
        +
      • Remove NULL + definition and add + include for stdio.h
      • +
      +
    • stm32_hal_legacy.h
    • +
        +
      • Update method + + + + to manage deference in + alias implementation between + all STM32 families
      • +
      +
    • stm32f4xx_hal_ppp.c
    • +
        +
      • HAL_PPP_Init(): update + to force the + HAL_PPP_STATE_RESET before + calling the HAL_PPP_MspInit()
      • +
      +
    +
+
    +
  • HAL + + + + RCC update
  • +
      +
    • Add new + function HAL_RCCEx_GetPeriphCLKFreq()
    • +
    • Move RCC_PLLInitTypeDef + structure to extension file + and add the new PLLR field + specific to STM32F446xx devices
    • +
    • Move the + following functions to + extension file and add a + __weak attribute in generic driver + + + + : this + update is related to new + system clock source (PLL/PLLR) + added and only available for + STM32F44xx devices
    • +
        +
      • HAL_RCC_OscConfig()
      • +
      • HAL_RCC_GetSysClockFreq()
      • +
      • HAL_RCC_GetOscConfig()
      • +
      +
    • Move the + following macro to extension + file as they have device + dependent implementation
    • +
        +
      • __HAL_RCC_PLL_CONFIG()
      • +
      • __HAL_RCC_PLLI2S_CONFIG()
      • +
      • __HAL_RCC_I2S_CONFIG()
      • +
      +
    • Add new + structure RCC_PLLI2SInitTypeDef + containing new PLLI2S + division factors used only w/ + STM32F446xx devices
    • +
    • Add new + structure RCC_PLLSAIInitTypeDef + containing new PLLSAI + division factors used only w/ + STM32F446xx devices
    • +
    • Add new RCC_PeriphCLKInitTypeDef + to support the peripheral + source clock selection for (I2S, + + + + SAI, SDIO, FMPI2C, CEC, + SPDIFRX and CLK48)
    • +
    • Update the HAL_RCCEx_PeriphCLKConfig() + and HAL_RCCEx_GetPeriphCLKConfig() + + + + + functions to support the + new peripherals Clock source + selection
    • +
    • Add __HAL_RCC_PLL_CONFIG() + macro (the number of parameter + and the implementation depend + on the device part number)
    • +
    • Add __HAL_RCC_PLLI2S_CONFIG() + macro(the number of parameter + and the implementation depend + on device part number)
    • +
    • Update __HAL_RCC_PLLSAI_CONFIG() + macro to support new PLLSAI + factors (PLLSAIM and + PLLSAIP)
    • +
    • Add new + macros for clock + enable/Disable for the + following peripherals (CEC, + + + + SPDIFRX, SAI2, QUADSPI)
    • +
    • Add the + following new macros for clock + source selection + + + + :
    • +
        +
      • __HAL_RCC_SAI1_CONFIG() + / + __HAL_RCC_GET_SAI1_SOURCE()
      • +
      • __HAL_RCC_SAI2_CONFIG() + / + __HAL_RCC_GET_SAI2_SOURCE()
      • +
      • __HAL_RCC_I2S1_CONFIG() + / + __HAL_RCC_GET_I2S1_SOURCE()
      • +
      • __HAL_RCC_I2S2_CONFIG() + / + __HAL_RCC_GET_I2S2_SOURCE()
      • +
      • __HAL_RCC_CEC_CONFIG() + / + __HAL_RCC__GET_CEC_SOURCE() +
      • +
      • __HAL_RCC_FMPI2C1_CONFIG() + / + __HAL_RCC_GET_FMPI2C1_SOURCE() +
      • +
      • __HAL_RCC_SDIO_CONFIG() + / + __HAL_RCC_GET_SDIO_SOURCE() +
      • +
      • __HAL_RCC_CLK48_CONFIG() + / + __HAL_RCC_GET_CLK48_SOURCE() +
      • +
      • __HAL_RCC_SPDIFRXCLK_CONFIG() + / + __HAL_RCC_GET_SPDIFRX_SOURCE()
      • +
      +
    • __HAL_RCC_PPP_CLK_ENABLE(): + + + + + Implement workaround to cover + RCC limitation regarding + peripheral enable delay
    • +
    • HAL_RCC_OscConfig() fix + issues: 
    • +
        +
      • Add a check + on LSERDY flag when + LSE_BYPASS is selected as + new state for LSE + oscillator.
      • +
      +
    • Add + new possible value RCC_PERIPHCLK_PLLI2S + + + + to be selected as PeriphClockSelection + parameter in the + + + + +  RCC_PeriphCLKInitTypeDef + structure to allow the + possibility to output the + PLLI2S on MCO without + activating the I2S or the SAI.
    • +
    • __HAL_RCC_HSE_CONFIG() +  macro: add + the comment below:
    • +
    +
+
+

 * + + + + + @note   Transition + HSE Bypass to HSE On and HSE + On to HSE Bypass are not + supported by this macro.
+  *         + + + + User should request a + transition to HSE Off first + and then HSE On or HSE Bypass.

+
+
    +
      +
    • __HAL_RCC_LSE_CONFIG()  macro: add + the comment below:
    • +
    +
+
+

  * + + + + + @note   Transition + LSE Bypass to LSE On and LSE + On to LSE Bypass are not + supported by this macro.
+   + *         + User should request a + transition to LSE Off first + and then LSE On or LSE Bypass.

+
+
    +
      +
    • Add the + following new macros for + PLL source and PLLM selection + + + + :
    • +
        +
      • __HAL_RCC_PLL_PLLSOURCE_CONFIG()
      • +
      • __HAL_RCC_PLL_PLLM_CONFIG()
      • +
      +
    • Macros + rename:
    • +
        +
      • HAL_RCC_OTGHS_FORCE_RESET() +by HAL_RCC_USB_OTG_HS_FORCE_RESET()
      • +
      • HAL_RCC_OTGHS_RELEASE_RESET() +by HAL_RCC_USB_OTG_HS_RELEASE_RESET()
      • +
      • HAL_RCC_OTGHS_CLK_SLEEP_ENABLE() +by HAL_RCC_USB_OTG_HS_CLK_SLEEP_ENABLE()
      • +
      • HAL_RCC_OTGHS_CLK_SLEEP_DISABLE() +by HAL_RCC_USB_OTG_HS_CLK_SLEEP_DISABLE()
      • +
      • HAL_RCC_OTGHSULPI_CLK_SLEEP_ENABLE() +by HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_ENABLE()
      • +
      • HAL_RCC_OTGHSULPI_CLK_SLEEP_DISABLE() +by HAL_RCC_USB_OTG_HS_ULPI_CLK_SLEEP_DISABLE()
      • +
      +
    • Add __HAL_RCC_SYSCLK_CONFIG() + new macro to configure the + system clock source (SYSCLK)
    • +
    • __HAL_RCC_GET_SYSCLK_SOURCE() + updates:
    • +
        +
      • Add new RCC + Literals:
      • +
          +
        • RCC_SYSCLKSOURCE_STATUS_HSI
        • +
        • RCC_SYSCLKSOURCE_STATUS_HSE
        • +
        • RCC_SYSCLKSOURCE_STATUS_PLLCLK
        • +
        • RCC_SYSCLKSOURCE_STATUS_PLLRCLK
        • +
        +
      •  Update + + + + macro description to refer + to the literals above +
      • +
      +
    +
  • HAL + + + + PWR update
  • +
      +
    • Add new + define PWR_WAKEUP_PIN2
    • +
    • Add new API + to Control/Get VOS bits + of CR register
    • +
        +
      • HAL_PWR_HAL_PWREx_ControlVoltageScaling()
      • +
      • HAL_PWREx_GetVoltageRange()
      • +
      +
    • __HAL_PWR_ + VOLTAGESCALING_CONFIG(): Implement + workaround to cover VOS + limitation delay when PLL is + enabled after setting the VOS + configuration
    • +
    +
  • HAL + + + + GPIO update
  • +
      +
    • Add the new + Alternate functions literals + related to remap for SPI, + + + + USART, I2C, SPDIFRX, CEC + and QSPI
    • +
    • HAL_GPIO_DeInit(): + + + + Update to check if GPIO + Pin x is already used in EXTI + mode on another GPIO Port + before De-Initialize the EXTI + registers
    • +
    +
  • HAL + + + + FLASH update
  • +
      +
    • __HAL_FLASH_INSTRUCTION_CACHE_RESET() + macro: update to reset +  ICRST bit in + the ACR register after + setting it.
    • +
    • __HAL_FLASH_DATA_CACHE_RESET() macro: + + + + + update to reset +  DCRST bit in the ACR + register after setting it.
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • Add new + literal: ADC_SOFTWARE_START to + be used as possible value for + the ExternalTrigConv + parameter in the ADC_InitTypeDef + structure to select the ADC + software trigger mode.
    • +
    • IS_ADC_CHANNEL() + macro update to don't assert + stop the ADC_CHANNEL_TEMPSENSOR + value
    • +
    • HAL_ADC_PollForConversion(): update to + manage particular case when + ADC configured in DMA mode and + ADC sequencer with several + ranks and polling for end of + each conversion
    • +
    • HAL_ADC_Start()/HAL_ADC_Start_IT() + /HAL_ADC_Start_DMA() + + + + + update:
    • +
        +
      • unlock the + process before starting the + ADC software conversion.
      • +
      • Optimize + the ADC stabilization delays
      • +
      +
    • __HAL_ADC_GET_IT_SOURCE() + update macro implementation
    • +
    • Add more + details in 'How to use this + driver' section
    • +
    +
  • HAL + + + + DAC update
  • +
      +
    • Add new macro + to check if the specified DAC + interrupt source is enabled or + disabled
    • +
        +
      • __HAL_DAC_GET_IT_SOURCE()
      • +
      +
    • HAL_DACEx_TriangleWaveGeneration() update to + use DAC CR bit mask definition
    • +
    • HAL_DACEx_NoiseWaveGeneration() update to + use DAC CR bit mask definition
    • +
    +
  • HAL + + + + CAN update
  • +
      +
    • CanTxMsgTypeDef structure: + update to use uint8_t Data[8] + + + + + instead of + uint32_t Data[8]
    • +
    • CanRxMsgTypeDef structure: + update to use uint8_t Data[8] + instead of + uint32_t Data[8]
    • +
    +
+
    +
  • HAL + + + + RTC update
  • +
      +
    • Update to + use CMSIS mask definition + instead of hardcoded values (EXTI_IMR_IM17, + EXTI_IMR_IM19..)
    • +
    +
  • HAL + + + + LTDC update
  • +
      +
    • LTDC_SetConfig() update to + allow the drawing + of partial bitmap in + active layer.
    • +
    +
  • HAL + + + + USART update
  • +
      +
    • HAL_USART_Init() fix USART + baud rate configuration + issue: USART baud rate is + twice Higher than expected
    • +
    +
  • HAL + + + + SMARTCARD update
  • +
      +
    • HAL_SMARTCARD_Transmit_IT() update to + force the disable for the ERR + interrupt to avoid the OVR + interrupt
    • +
    • HAL_SMARTCARD_IRQHandler() + update check condition + for transmission end
    • +
    • Clean up: + remove the following + literals that aren't used in + smartcard mode
    • +
        +
      • SMARTCARD_PARITY_NONE
      • +
      • SMARTCARD_WORDLENGTH_8B
      • +
      • SMARTCARD_STOPBITS_1
      • +
      • SMARTCADR_STOPBITS_2
      • +
      +
    +
  • HAL + + + + SPI update
  • +
      +
    • HAL_SPI_Transmit_DMA()/HAL_SPI_Receive_DMA()/HAL_SPI_TarnsmitReceive_DMA() + update to unlock + the process before + enabling the SPI peripheral
    • +
    • HAL_SPI_Transmit_DMA() update to + manage correctly the DMA RX + stream in SPI Full duplex mode
    • +
    • Section + SPI_Exported_Functions_Group2 update + to remove duplication in *.chm + UM
    • +
    +
  • HAL + + + + CRYP update
  • +
      +
    • Update to + manage multi instance:
    • +
        +
      • Add new + parameter Instance in the CRYP_HandleTypeDef + Handle structure.
      • +
      • Add new + parameter in all HAL CRYP + macros
      • +
          +
        • example: __HAL_CRYP_ENABLE() +  updated by + __HAL_CRYP_ENABLE(__HANDLE__)
        • +
        +
      +
    +
  • HAL + + + + DCMI update
  • +
      +
    • Add an + extension + driver stm32f4xx_hal_dcmi_ex.c/h + to manage the support of new + Black and White feature +
    • +
    • Add  __weak attribute + for HAL_DCMI_Init() + function and add a new + implementation in the + extension driver to manage the + black and white configuration + only available in the  + STM32F446xx devices. +
    • +
    • Move DCMI_InitTypeDef + structure to extension driver + and add the + following new fields + related to black and white + feature: ByteSelectModeByteSelectStartLineSelectMode + and LineSelectStart
    • +
    +
  • HAL + + + + PCD update
  • +
      +
    • Add the + support of LPM feature
    • +
        +
      • add PCD_LPM_StateTypeDef + enum
      • +
      • update PCD_HandleTypeDef + structure to support the LPM + feature
      • +
      • add new + functions HAL_PCDEx_ActivateLPM(), + + + + + HAL_PCDEx_DeActivateLPM() + + + + + and HAL_PCDEx_LPM_Callback() + + + + + in the + stm32f4xx_hal_pcd_ex.h/.c + files
      • +
      +
    +
  • HAL + + + + TIM update
  • +
      +
    • Add  + TIM_TIM11_SPDIFRX + + + + define
    • +
    +
  • HAL + + + + SAI update
  • +
      +
    • Add + stm32f4xx_hal_sai_ex.h/.c + files for the SAI_BlockSynchroConfig() + and the SAI_GetInputClock() + + + + + management
    • +
    • Add new + defines HAL_SAI_ERROR_AFSDET, + HAL_SAI_ERROR_LFSDET, + HAL_SAI_ERROR_CNREADY, + HAL_SAI_ERROR_WCKCFG, + HAL_SAI_ERROR_TIMEOUT in the SAI_Error_Code + group
    • +
    • Add new + defines SAI_SYNCEXT_DISABLE, + SAI_SYNCEXT_IN_ENABLE, + SAI_SYNCEXT_OUTBLOCKA_ENABLE, + SAI_SYNCEXT_OUTBLOCKB_ENABLE + for the SAI External + synchronization
    • +
    • Add new + defines SAI_I2S_STANDARD, + SAI_I2S_MSBJUSTIFIED, + SAI_I2S_LSBJUSTIFIED, + SAI_PCM_LONG and SAI_PCM_SHORT + for the SAI Supported protocol
    • +
    • Add new + defines + SAI_PROTOCOL_DATASIZE_16BIT, + SAI_PROTOCOL_DATASIZE_16BITEXTENDED, + SAI_PROTOCOL_DATASIZE_24BIT + and + SAI_PROTOCOL_DATASIZE_32BIT + for SAI protocol data size
    • +
    • Add SAI + Callback prototype definition
    • +
    • Update SAI_InitTypeDef + structure by adding new + fields: SynchroExt, + Mckdiv, + MonoStereoMode, + CompandingMode, + TriState
    • +
    • Update SAI_HandleTypeDef + structure:
    • +
        +
      • remove + uint16_t *pTxBuffPtr, + *pRxBuffPtr, + TxXferSize, + RxXferSize, + TxXferCount + and RxXferCount + and replace them + respectively by uint8_t *pBuffPtr, + uint16_t XferSize and + + + + + uint16_t XferCount
      • +
      • add mutecallback + field
      • +
      • add struct + __SAI_HandleTypeDef + *hsai field
      • +
      +
    • Remove + SAI_CLKSOURCE_PLLR and + SAI_CLOCK_PLLSRC defines
    • +
    • Add + SAI_CLKSOURCE_NA define
    • +
    • Add + SAI_AUDIO_FREQUENCY_MCKDIV + define
    • +
    • Add + SAI_SPDIF_PROTOCOL define
    • +
    • Add + SAI_SYNCHRONOUS_EXT define
    • +
    • Add new + functions HAL_SAI_InitProtocol(), + + + + + HAL_SAI_Abort(), + + + + + HAL_SAI_EnableTxMuteMode(), + + + + + HAL_SAI_DisableTxMuteMode(), + + + + + HAL_SAI_EnableRxMuteMode(), + + + + + HAL_SAI_DisableRxMuteMode()
    • +
    • Update HAL_SAI_Transmit(), + + + + + HAL_SAI_Receive(), + + + + + HAL_SAI_Transmit_IT(), + + + + + HAL_SAI_Receive_IT(), + + + + + HAL_SAI_Transmit_DMA(), + + + + + HAL_SAI_Receive_DMA() + + + + + functions to use uint8_t *pData + instead of uint16_t *pData + --> This update is mainly + impacting the compatibility + with previous driver + version.
    • +
    +
  • HAL + + + + I2S update
  • +
      +
    • Split the + following + functions between Generic + and Extended API based on full + duplex management and add the + attribute __weak in the + Generic API
    • +
        +
      • HAL_I2S_Init(), +HAL_I2S_DMAPause(), HAL_I2S_DMAStop(), HAL_I2S_DMAResume(), HAL_I2S_IRQHandle() +
      • +
      +
    • Move the + following static functions + from generic to extension driver
    • +
        +
      •  I2S_DMARxCplt() + and I2S_DMATxCplt()
      • +
      +
    • Remove static + attribute from I2S_Transmit_IT() + and I2S_Receive_IT() functions
    • +
    • Move I2SxEXT() + macro to extension file
    • +
    • Add + I2S_CLOCK_PLLR and + I2S_CLOCK_PLLSRC defines for + I2S clock source
    • +
    • Add new + function I2S_GetInputClock()
    • +
    +
  • HAL + + + + LL FMC update
  • +
      +
    • Add WriteFifo + and PageSize + fields in the FMC_NORSRAM_InitTypeDef + structure
    • +
    • Add + FMC_PAGE_SIZE_NONE, + FMC_PAGE_SIZE_128, + FMC_PAGE_SIZE_256, + FMC_PAGE_SIZE_1024, + FMC_WRITE_FIFO_DISABLE, + FMC_WRITE_FIFO_ENABLE defines
    • +
    • Update FMC_NORSRAM_Init(), + + + + + FMC_NORSRAM_DeInit() + + + + + and FMC_NORSRAM_Extended_Timing_Init() functions
    • +
    +
  • HAL + + + + LL USB update
  • +
      +
    • Update USB_OTG_CfgTypeDef + structure to support LPM, lpm_enable + field added
    • +
    • Update USB_HostInit() + and USB_DevInit() + + + + + functions to support the VBUS + Sensing B activation
    • +
    +
+

V1.2.0 + + + + / 26-December-2014

+

Main Changes

+
    +
  • Maintenance + + + + release to fix known defects + and enhancements implementation
  • +
+
    +
  • Macros + + + + and literals renaming to + ensure compatibles across + STM32 series, + backward compatibility + maintained thanks to new added + file stm32_hal_legacy.h under + + + + /Inc/Legacy
  • +
  • Add + *.chm UM for all drivers, a UM + is provided for each superset RPN
  • +
  • Update + + + + drivers to be C++ compliant
  • +
  • Several + + + + update on source code + formatting, for better UM + generation (i.e. + Doxygen + tags updated)
  • +
  • Two + + + + changes done on the HAL + requires an update on the + application code based on HAL + V1.1.0
  • +
      +
    • LSI_VALUE constant has + been corrected in + stm32f4xx_hal_conf.h file, its + value changed from 40 KHz + to 32 KHz
    • +
    • UART, USART, + IRDA and SMARTCARD + (referenced as PPP + here below) drivers: + in DMA transmit process, the + code has been updated to avoid + waiting on TC flag under DMA + ISR, PPP TC interrupt + is used instead. Below the + update to be done on user + application:
    • +
        +
      • Configure + and enable the USART IRQ in + HAL_PPP_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, PPP_IRQHandler() + function: add a call to HAL_PPP_IRQHandler() + + + + function
      • +
      +
    +
+
    +
  • HAL + + + + generic + update
  • +
+
    +
      +
    • stm32f4xx_hal_def.h
    • +
        +
      • Update NULL + definition to fix C++ + compilation issue
      • +
      • Add UNUSED() + macro
      • +
      • Add a new + define __NOINLINE to be used + for the no inline code + independent from tool chain
      • +
      +
    • stm32f4xx_hal_conf_template.h
    • +
        +
      • LSI_VALUE constant + has been corrected, + its value changed from 40 KHz + to 32 KHz
      • +
      +
    +
+
    +
      +
    • Update all + macros and literals naming to + be uper + case
    • +
    • ErrorCode parameter in + PPP_HandleTypeDef + structure updated + to uint32_t instead + of enum HAL_PPP_ErrorTypeDef
    • +
    • Remove the + + + + unused FLAG and IT assert macros
    • +
    +
  • HAL + + + + ADC update
  • +
      +
    • Fix temperature + + + + + sensor channel configuration + issue for STM32F427/437xx + + + + +  and STM32F429/439xx + + + + devices
    • +
    +
  • HAL + + + + DAC update
  • +
      +
    • HAL_DAC_ConfigChannel(): update the + access to the DAC peripheral + registers via the hdac + handle instance
    • +
    • HAL_DAC_IRQHandler(): update to + check on both DAC_FLAG_DMAUDR1 + and DAC_FLAG_DMAUDR2
    • +
    • HAL_DACEx_NoiseWaveGenerate(): update to + reset DAC CR register before + setting the new DAC + configuration
    • +
    • HAL_DACEx_TriangleWaveGenerate(): update to + reset DAC CR register before + setting the new DAC + configuration
    • +
    +
  • HAL + + + + CAN update
  • +
      +
    • Unlock the + CAN process when communication + error occurred
    • +
    +
  • HAL + + + + CORTEX update
  • +
      +
    • Add new macro + IS_NVIC_DEVICE_IRQ() + to check on negative values of + IRQn + parameter
    • +
    +
+

§  + + + + + HAL CRYP update

+
    +
      +
    • HAL_CRYP_DESECB_Decrypt_DMA(): fix the + inverted pPlainData + and pCypherData + parameters issue
    • +
    • CRYPEx_GCMCCM_SetInitVector(): remove + the IVSize + parameter as the key length + 192bits and 256bits are not + supported by this version
    • +
    • Add restriction for + + + + + the CCM Encrypt/Decrypt API's + that only DataType + equal to 8bits is supported
    • +
    • HAL_CRYPEx_AESGCM_Finish():
    • +
        +
      • Add restriction + + + + + that the implementation is + limited to 32bits inputs + data length  (Plain/Cyphertext, + + + + Header) compared with GCM stadards + specifications (800-38D)
      • +
      • Update Size + parameter on 32bits instead + of 16bits
      • +
      • Fix issue + with 16-bit Data Type: + update to use intrinsic __ROR() + instead of __REV16()
      • +
      +
    +
+

§  + + + + + HAL DCMI update

+
    +
      +
    • HAL_DCMI_ConfigCROP(): Invert + assert macros to check Y0 and + Ysize + parameters
    • +
    +
+

§  + + + + + HAL DMA update

+
    +
      +
    • HAL_DMA_Init(): Update to + + + + + clear the DBM bit in the + SxCR + register before setting the + new configuration
    • +
    • DMA_SetConfig(): + add to clear the DBM + bit in the SxCR + register
    • +
    +
+

§  + + + + + HAL FLASH update

+
    +
      +
    • Add "HAL_" + prefix in the defined values + for the FLASH error code
    • +
        +
      • Example: FLASH_ERROR_PGP + renamed by HAL_FLASH_ERROR_PGP
      • +
      +
    • Clear the + + + + Flash ErrorCode + in the FLASH_WaitForLastOperation() + function
    • +
    • Update FLASH_SetErrorCode() + function to use "|=" + operant to update the Flash ErrorCode + parameter in the FLASH handle
    • +
    • IS_FLASH_ADDRESS(): Update the + macro check using '<=' + condition instead of '<'
    • +
    • IS_OPTIONBYTE(): Update the + macro check using '<=' + condition instead of '<'
    • +
    • Add "FLASH_" + + + + + prefix in the defined values + of FLASH Type Program + parameter
    • +
        +
      • Example: TYPEPROGRAM_BYTE + renamed by FLASH_TYPEPROGRAM_BYTE
      • +
      +
    • Add "FLASH_" + + + + + prefix in the defined values + of FLASH Type Erase parameter
    • +
        +
      • Example: TYPEERASE_SECTORS + renamed by FLASH_TYPEERASE_SECTORS
      • +
      +
    • Add "FLASH_" + + + + + prefix in the defined values + of FLASH Voltage Range + parameter
    • +
        +
      • Example: VOLTAGE_RANGE_1 + renamed by FLASH_VOLTAGE_RANGE_1
      • +
      +
    • Add "OB_" + + + + + prefix in the defined values + of FLASH WRP State parameter
    • +
        +
      • Example: WRPSTATE_ENABLE + renamed by OB_WRPSTATE_ENABLE
      • +
      +
    • Add "OB_" + + + + + prefix in the defined values + of the FLASH PCROP State + parameter
    • +
        +
      • PCROPSTATE_DISABLE  + updated by OB_PCROP_STATE_DISABLE
      • +
      • PCROPSTATE_ENABLE +  updated by OB_PCROP_STATE_ENABLE
      • +
      +
    • Change + "OBEX" prefix by + "OPTIONBYTE" prefix in these + defines:
    • +
        +
      • OBEX_PCROP + + + + by OPTIONBYTE_PCROP 
      • +
      • OBEX_BOOTCONFIG + + + + by OPTIONBYTE_BOOTCONFIG
      • +
      +
    +
+

§  + + + + + HAL ETH update

+
    +
      +
    • Fix macros + naming typo
    • +
    +
+
    +
      +
        +
      • Update + __HAL_ETH_EXTI_SET_RISING_EGDE_TRIGGER() + by + __HAL_ETH_EXTI_SET_RISING_EDGE_TRIGGER()
      • +
      • Update + __HAL_ETH_EXTI_SET_FALLING_EGDE_TRIGGER() +by __HAL_ETH_EXTI_SET_FALLING_EDGE_TRIGGER()
      • +
      +
    +
+

§  + + + + + HAL PWR update

+
    +
      +
    • Add new API + to manage SLEEPONEXIT and + SEVONPEND bits of SCR register
    • +
        +
      • HAL_PWR_DisableSleepOnExit()
      • +
      • HAL_PWR_EnableSleepOnExit()
      • +
      • HAL_PWR_EnableSEVOnPend()
      • +
      • HAL_PWR_DisableSEVOnPend()
      • +
      +
    • HAL_PWR_EnterSTOPMode()
    • +
        +
      • Update to + + + + clear the CORTEX SLEEPDEEP + bit of SCR register + before entering in sleep mode
      • +
      • Update + usage of __WFE() + in low power entry function: + if there is a pending event, + calling __WFE() will not + enter the CortexM4 core to + sleep mode. The solution is + to made the call below; the + first __WFE() + is always ignored and clears + the event if one was already + pending, the second is + always applied
      • +
      +
    +
+
+

__SEV()
+
__WFE()
+
__WFE()

+
+
    +
      +
    • Add + new PVD configuration modes
    • +
        +
      • PWR_PVD_MODE_NORMAL
      • +
      • PWR_PVD_MODE_EVENT_RISING 
      • +
      • PWR_PVD_MODE_EVENT_FALLING
      • +
      • PWR_PVD_MODE_EVENT_RISING_FALLING
      • +
      +
    • Add new + macros to manage PVD Trigger
    • +
        +
      • __HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE()
      • +
      • __HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE(
      • +
      • __HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE()
      • +
      • __HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE()
      • +
      • __HAL_PWR_PVD_EXTI_ENABLE_RISING_FALLING_EDGE()
      • +
      • __HAL_PWR_PVD_EXTI_DISABLE_RISING_FALLING_EDGE()
      • +
      +
    • PVD macros:
    • +
        +
      • Remove the + __EXTILINE__ parameter
      • +
      • Update to + use prefix "__HAL_PWR_PVD_" + instead of  prefix + "__HAL_PVD"
      • +
      +
    +
+
    +
      +
    • Rename HAL_PWR_PVDConfig() + by HAL_PWR_ConfigPVD()
    • +
    • Rename HAL_PWREx_ActivateOverDrive() + by HAL_PWREx_EnableOverDrive() + + + + +
    • +
    • Rename HAL_PWREx_DeactivateOverDrive() + by HAL_PWREx_DisableOverDrive() + + + + +
    • +
    +
  • HAL + + + + GPIO update
  • +
      +
    • HAL_GPIO_Init()/HAL_GPIO_DeInit(): add a call + to the CMSIS assert macro + to check GPIO instance: + IS_GPIO_ALL_INSTANCE() 
    • +
    • HAL_GPIO_WritePin(): update to + write in BSRR register
    • +
    • Rename GPIO_GET_SOURCE() + by GET_GPIO_INDEX() and + + + + move this later to file  + stm32f4xx_hal_gpio_ex.h
    • +
    • Add new + define for alternate function + GPIO_AF5_SPI3 for + STM32F429xx/439xx and + STM32F427xx/437xx devices
    • +
    +
  • HAL + + + + HASH update
  • +
      +
    • HAL_HASH_MD5_Start_IT(): + + + + + fix input + address management issue
    • +
    +
  • HAL + + + + RCC update
  • +
      +
    • Rename the + following Macros
    • +
        +
      • __PPP_CLK_ENABLE()  + + + + + by + __HAL_RCC_PPP_CLK_ENABLE()
      • +
      • __PPP_CLK_DISABLE()  + + + + + by + __HAL_RCC_PPP_CLK_DISABLE()
      • +
      • __PPP_FORCE_RESET()  + + + + + by + __HAL_RCC_PPP_FORCE_RESET()
      • +
      • __PPP_RELEASE_RESET()  + + + + + by + __HAL_RCC_PPP_RELEASE_RESET()
      • +
      • __PPP_CLK_SLEEP_ENABLE() + by + __HAL_RCC_PPP_CLK_SLEEP_ENABLE()
      • +
      • __PPP_CLK_SLEEP_DISABLE() + by + __HAL_RCC_PPP_CLK_SLEEP_DISABLE()
      • +
      +
    • IS_RCC_PLLSAIN_VALUE() + macro: update the check + condition
    • +
    • Add + description of RCC known Limitations
    • +
    • Rename HAL_RCC_CCSCallback() + by HAL_RCC_CSSCallback()
    • +
    • HAL_RCC_OscConfig() fix + issues: 
    • +
        +
      • Remove the + disable of HSE + oscillator when + HSE_BYPASS is used as + system clock source or as + PPL clock source
      • +
      • Add a check + on HSERDY flag + when HSE_BYPASS is + selected as new state + for HSE oscillator.
      • +
      +
    • Rename + __HAL_RCC_I2SCLK() + by __HAL_RCC_I2S_Config()
    • +
    +
+

§  + + + + + HAL I2S update

+
    +
      +
    • HAL_I2S_Init(): add check + on I2S instance + using CMSIS macro IS_I2S_ALL_INSTANCE() 
    • +
    • HAL_I2S_IRQHandler() + update for compliancy w/ C++
    • +
    • Add use + of tmpreg + variable in __HAL_I2S_CLEAR_OVRFLAG() + and __HAL_I2S_CLEAR_UDRFLAG() + macro for compliancy with C++
    • +
    • HAL_I2S_GetError(): update to + return uint32_t instead of + HAL_I2S_ErrorTypeDef + enumeration
    • +
    +
+

§  + + + + + HAL I2C update

+
    +
      +
    • Update to + + + + + clear the POS bit in the + CR1 register at the end + of HAL_I2C_Master_Read_IT() + and HAL_I2C_Mem_Read_IT() + process
    • +
    • Rename + HAL_I2CEx_DigitalFilter_Config()  + + + + by + HAL_I2CEx_ConfigDigitalFilter() +
    • +
    • Rename + HAL_I2CEx_AnalogFilter_Config()  + + + + by + HAL_I2CEx_ConfigAnalogFilter() +
    • +
    • Add use + of tmpreg + variable in __HAL_I2C_CLEAR_ADDRFLAG() + and __HAL_I2C_CLEAR_STOPFLAG() + macro for compliancy with + C++
    • +
    +
  • HAL + + + + IrDA update
  • +
      +
    • DMA transmit + process; the code has been + updated to avoid waiting on TC + flag under DMA ISR, IrDA TC + interrupt is used instead. + Below the update to be done on + user application:
    • +
        +
      • Configure + and enable the USART IRQ in + HAL_IRDA_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, UASRTx_IRQHandler() + function: add a call to HAL_IRDA_IRQHandler() + + + + function
      • +
      +
    • IT transmit + process; the code has been + updated to avoid waiting on TC + flag under IRDA ISR, IrDA TC + interrupt is used instead. No + impact on user application
    • +
    • Rename + Macros: add prefix "__HAL"
    • +
        +
      • __IRDA_ENABLE() + by __HAL_IRDA_ENABLE()
      • +
      • __IRDA_DISABLE() + by __HAL_IRDA_DISABLE()
      • +
      +
    • Add new user + macros to manage the sample + method feature
    • +
        +
      • __HAL_IRDA_ONE_BIT_SAMPLE_ENABLE()
      • +
      • __HAL_IRDA_ONE_BIT_SAMPLE_DISABLE()
      • +
      +
    • HAL_IRDA_Transmit_IT(): update to + remove the enable of the + parity error interrupt
    • +
    • Add use + of tmpreg + variable in __HAL_IRDA_CLEAR_PEFLAG() + macro for compliancy with + C++
    • +
    • HAL_IRDA_Transmit_DMA() update to + follow the + right procedure + "Transmission using DMA"  + in the reference manual
    • +
        +
      • Add clear + the TC flag in the SR + register before enabling the + DMA transmit + request
      • +
      +
    +
  • HAL + + + + IWDG update
  • +
      +
    • Rename the + defined IWDG keys: 
    • +
        +
      • KR_KEY_RELOAD + + + + by IWDG_KEY_RELOAD
      • +
      • KR_KEY_ENABLE + + + + by IWDG_KEY_ENABLE
      • +
      • KR_KEY_EWA + by + IWDG_KEY_WRITE_ACCESS_ENABLE
      • +
      • KR_KEY_DWA + by + IWDG_KEY_WRITE_ACCESS_DISABLE
      • +
      +
    •  Add new + macros + __HAL_IWDG_RESET_HANDLE_STATE() + and + __HAL_IWDG_CLEAR_FLAG() 
    • +
    • Update + __HAL_IWDG_ENABLE_WRITE_ACCESS() + and + __HAL_IWDG_DISABLE_WRITE_ACCESS() + as private macro
    • +
    +
+

§  + + + + + HAL SPI update

+
    +
      +
    • HAL_SPI_TransmitReceive_DMA() update to + remove the  DMA Tx Error + Callback initialization when + SPI RxOnly + mode is selected
    • +
    • Add use of UNUSED(tmpreg) + in __HAL_SPI_CLEAR_MODFFLAG(), + __HAL_SPI_CLEAR_OVRFLAG(), + __HAL_SPI_CLEAR_FREFLAG() to + fix "Unused variable" warning + with TrueSTUDIO.
    • +
    • Rename + Literals: remove "D" from + "DISABLED" and "ENABLED"
    • +
        +
      • SPI_TIMODE_DISABLED by + + + + + SPI_TIMODE_DISABLE
      • +
      • SPI_TIMODE_ENABLED by SPI_TIMODE_ENABLE
      • +
      • SPI_CRCCALCULATION_DISABLED + by + + + + +  SPI_CRCCALCULATION_DISABLE
      • +
      • SPI_CRCCALCULATION_ENABLED + by + + + + +  SPI_CRCCALCULATION_ENABLE
      • +
      +
    • Add use + of tmpreg + variable in __HAL_SPI_CLEAR_MODFFLAG(), + + + + + __HAL_SPI_CLEAR_FREFLAG() and + __HAL_SPI_CLEAR_OVRFLAG() + macros for compliancy + with C++
    • +
    +
+

§  + + + + + HAL SDMMC update

+
    +
      +
    • IS_SDIO_ALL_INSTANCE() +  macro moved to CMSIS + files
    • +
    +
  • HAL + + + + LTDC update
  • +
      +
    • HAL_LTDC_ConfigCLUT: optimize + the function when pixel format +is LTDC_PIXEL_FORMAT_AL44 
    • +
        +
      • Update the + size of color look up table + to 16 instead of 256 when + the pixel format + is LTDC_PIXEL_FORMAT_AL44 +
      • +
      +
    +
  • HAL + + + + NAND update
  • +
      +
    • Rename NAND + Address structure to NAND_AddressTypeDef + instead of NAND_AddressTypedef
    • +
    • Update the + used algorithm of these functions
    • +
        +
      • HAL_NAND_Read_Page()
      • +
      • HAL_NAND_Write_Page()
      • +
      • HAL_NAND_Read_SpareArea()
      • +
      • HAL_NAND_Write_SpareArea()
      • +
      +
    • HAL_NAND_Write_Page(): move + initialization of tickstart + before while loop
    • +
    • HAL_NAND_Erase_Block(): add whait + until NAND status is ready + before exiting this function
    • +
    +
  • HAL + + + + NOR update
  • +
      +
    • Rename NOR + Address structure to NOR_AddressTypeDef + instead of NOR_AddressTypedef
    • +
    • NOR Status + literals renamed
    • +
        +
      • NOR_SUCCESS + by HAL_NOR_STATUS_SUCCESS
      • +
      • NOR_ONGOING + by HAL_NOR_STATUS_ONGOING
      • +
      • NOR_ERROR + by HAL_NOR_STATUS_ERROR
      • +
      • NOR_TIMEOUT + by HAL_NOR_STATUS_TIMEOUT
      • +
      +
    • HAL_NOR_GetStatus() update to + fix Timeout issue + and exit from waiting + loop when timeout occurred
    • +
    +
  • HAL + + + + PCCARD update
  • +
      +
    • Rename PCCARD + Address structure to HAL_PCCARD_StatusTypeDef + instead of CF_StatusTypedef
    • +
    • PCCARD Status + literals renamed
    • +
        +
      • CF_SUCCESS + by HAL_PCCARD_STATUS_SUCCESS
      • +
      • CF_ONGOING + by HAL_PCCARD_STATUS_ONGOING
      • +
      • CF_ERROR + by HAL_PCCARD_STATUS_ERROR
      • +
      • CF_TIMEOUT + by HAL_PCCARD_STATUS_TIMEOUT
      • +
      +
    • Update "CF" + by "PCCARD" in functions, + literals + and macros
    • +
    +
  • HAL + + + + PCD update
  • +
      +
    • Rename functions
    • +
        +
      • HAL_PCD_ActiveRemoteWakeup() by HAL_PCD_ActivateRemoteWakeup()
      • +
      • HAL_PCD_DeActiveRemoteWakeup() by HAL_PCD_DeActivateRemoteWakeup()
      • +
      +
    • Rename literals
    • +
        +
      • USB_FS_EXTI_TRIGGER_RISING_EDGE + + + + + by + USB_OTG_FS_WAKEUP_EXTI_RISING_EDGE
      • +
      • USB_FS_EXTI_TRIGGER_FALLING_EDGE + + + + + by + USB_OTG_FS_WAKEUP_EXTI_FALLING_EDGE
      • +
      • USB_FS_EXTI_TRIGGER_BOTH_EDGE() + by + USB_OTG_FS_WAKEUP_EXTI_RISING_FALLING_EDGE
      • +
      • USB_HS_EXTI_TRIGGER_RISING_EDGE + + + + + by + USB_OTG_HS_WAKEUP_EXTI_RISING_EDGE 
      • +
      • USB_HS_EXTI_TRIGGER_FALLING_EDGE + + + + + by + USB_OTG_HS_WAKEUP_EXTI_FALLING_EDGE
      • +
      • USB_HS_EXTI_TRIGGER_BOTH_EDGE + + + + + by + USB_OTG_HS_WAKEUP_EXTI_RISING_FALLING_EDGE
      • +
      • USB_HS_EXTI_LINE_WAKEUP + + + + + by + USB_OTG_HS_EXTI_LINE_WAKEUP
      • +
      • USB_FS_EXTI_LINE_WAKEUP + + + + + by + USB_OTG_FS_EXTI_LINE_WAKEUP
      • +
      +
    • Rename USB + EXTI macros (FS, HS + + + + referenced as SUBBLOCK + here below)
    • +
        +
      • __HAL_USB_SUBBLOCK_EXTI_ENABLE_IT() +  by  + __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_ENABLE_IT()  
      • +
      • __HAL_USB_SUBBLOCK_EXTI_DISABLE_IT() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_DISABLE_IT()
      • +
      • __HAL_USB_SUBBLOCK_EXTI_GET_FLAG() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_GET_FLAG() 
      • +
      • __HAL_USB_SUBBLOCK_EXTI_CLEAR_FLAG() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_CLEAR_FLAG()
      • +
      • __HAL_USB_SUBBLOCK_EXTI_SET_RISING_EGDE_TRIGGER() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_ENABLE_RISING_EDGE()
      • +
      • __HAL_USB_SUBBLOCK_EXTI_SET_FALLING_EGDE_TRIGGER() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_ENABLE_FALLING_EDGE()
      • +
      • __HAL_USB_SUBBLOCK_EXTI_SET_FALLINGRISING_TRIGGER() + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE()
      • +
      • __HAL_USB_SUBBLOCK_EXTI_GENERATE_SWIT()  + + + + + by __HAL_USB_OTG_SUBBLOCK_WAKEUP_EXTI_GENERATE_SWIT()                                       +
      • +
      +
    +
+
    +
  • HAL + + + + RNG update
  • +
      +
    • Add new functions
    • +
        +
      • HAL_RNG_GenerateRandomNumber(): to + generate a 32-bits random + number, + return + random value in argument and + return HAL status.
      • +
      • HAL_RNG_GenerateRandomNumber_IT(): to +  start generation of + the 32-bits random + number, user should call + the HAL_RNG_ReadLastRandomNumber() + + + + + function under the HAL_RNG_ReadyCallback() + + + + to get the generated random + value.
      • +
      • HAL_RNG_ReadLastRandomNumber(): to + return the last random value + stored in the RNG handle
      • +
      +
    • HAL_RNG_GetRandomNumber(): return + value update (obsolete), + replaced by HAL_RNG_GenerateRandomNumber()
    • +
    • HAL_RNG_GetRandomNumber_IT(): wrong + implementation (obsolete), + replaced by HAL_RNG_GenerateRandomNumber_IT()
    • +
    • __HAL_RNG_CLEAR_FLAG() + macro (obsolete), replaced by + new __HAL_RNG_CLEAR_IT() macro
    • +
    • Add new + define for RNG ready + interrupt:  RNG_IT_DRDY
    • +
    +
  • HAL + + + + RTC update
  • +
      +
    • HAL_RTC_GetTime() and HAL_RTC_GetDate(): + + + + + add the comment below
    • +
    +
+
+
+

  + + + + + * @note You must call HAL_RTC_GetDate() + after HAL_RTC_GetTime() + + + + + to unlock the values
+
  + + + + + * in the higher-order + calendar shadow registers to + ensure consistency between + the time and date values.
+
  + + + + + * Reading RTC current time + locks the values in calendar + shadow registers until + Current date is read. 

+
+
+
    +
      +
    • Rename + literals: add prefix "__HAL"
    • +
        +
      • FORMAT_BIN by HAL_FORMAT_BIN
      • +
      • FORMAT_BCD + by HAL_FORMAT_BCD
      • +
      +
    • Rename macros + (ALARM, WAKEUPTIMER and + TIMESTAMP referenced + as SUBBLOCK here + below)
    • +
        +
      • __HAL_RTC_EXTI_ENABLE_IT() + by  __HAL_RTC_SUBBLOCK_EXTI_ENABLE_IT()
      • +
      • __HAL_RTC_EXTI_DISABLE_IT() + by  __HAL_RTC_SUBBLOCK_EXTI_DISABLE_IT()
      • +
      • __HAL_RTC_EXTI_CLEAR_FLAG() + by  __HAL_RTC_SUBBLOCK_EXTI_CLEAR_FLAG()
      • +
      • __HAL_RTC_EXTI_GENERATE_SWIT() + by __HAL_RTC_SUBBLOCK_EXTI_GENERATE_SWIT()
      • +
      +
    • Add new + macros (ALARM, + WAKEUPTIMER and TAMPER_TIMESTAMP + + + + referenced as SUBBLOCK + here below)
    • +
        +
      • __HAL_RTC_SUBBLOCK_GET_IT_SOURCE(
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_ENABLE_EVENT()
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_DISABLE_EVENT()
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_ENABLE_FALLING_EDGE()
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_DISABLE_FALLING_EDGE()
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_ENABLE_RISING_EDGE()
      • +
      • __HAL_RTC_SUBBLOCK_EXTI_DISABLE_RISING_EDGE()
      • +
      •  __HAL_RTC_SUBBLOCK_EXTI_ENABLE_RISING_FALLING_EDGE()
      • +
      •  __HAL_RTC_SUBBLOCK_EXTI_DISABLE_RISING_FALLING_EDGE()
      • +
      •  __HAL_RTC_SUBBLOCK_EXTI_GET_FLAG()
      • +
      +
    +
  • HAL + + + + SAI update
  • +
      +
    • Update + SAI_STREOMODE by SAI_STEREOMODE
    • +
    • Update FIFO + status Level defines in upper + case
    • +
    • Rename + literals: remove "D" from + "DISABLED" and "ENABLED"
    • +
        +
      • SAI_OUTPUTDRIVE_DISABLED + + + + +  by + SAI_OUTPUTDRIVE_DISABLE
      • +
      • SAI_OUTPUTDRIVE_ENABLED + + + + +  by + SAI_OUTPUTDRIVE_ENABLE
      • +
      • SAI_MASTERDIVIDER_ENABLED  by + SAI_MASTERDIVIDER_ENABLE
      • +
      • SAI_MASTERDIVIDER_DISABLED  by + SAI_MASTERDIVIDER_DISABLE
      • +
      +
    +
+
    +
  • HAL + + + + SD update
  • +
      +
    • Rename + SD_CMD_SD_APP_STAUS by SD_CMD_SD_APP_STATUS
    • +
    • SD_PowerON() updated to + add 1ms required power up + waiting time before starting + the SD initialization sequence
    • +
    • SD_DMA_RxCplt()/SD_DMA_TxCplt(): + + + + + add a call to + HAL_DMA_Abort()
    • +
    • HAL_SD_ReadBlocks() update to + set the defined + DATA_BLOCK_SIZE as SDIO DataBlockSize + parameter
    • +
    • HAL_SD_ReadBlocks_DMA()/HAL_SD_WriteBlocks_DMA() + update to call the HAL_DMA_Start_IT() + + + + function with DMA Datalength + set to BlockSize/4  + + + + + as the DMA is + configured in word 
    • +
    +
  • HAL + + + + SMARTCARD update 
  • +
      +
    • DMA transmit + process; the code has been + updated to avoid waiting on TC + flag under DMA ISR, SMARTCARD + TC interrupt is used instead. + Below the update to be done on + user application:
    • +
        +
      • Configure + and enable the USART IRQ in + HAL_SAMRTCARD_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, UASRTx_IRQHandler() + function: add a call to HAL_SMARTCARD_IRQHandler() + + + + + function
      • +
      +
    • IT transmit + process; the code has been + updated to avoid waiting on TC + flag under SMARTCARD + ISR, SMARTCARD TC + interrupt is used instead. No + impact on user application
    • +
    • Rename + macros: add prefix "__HAL"
    • +
        +
      • __SMARTCARD_ENABLE() + by __HAL_SMARTCARD_ENABLE()
      • +
      • __SMARTCARD_DISABLE() + by __HAL_SMARTCARD_DISABLE()
      • +
      • __SMARTCARD_ENABLE_IT() + by + __HAL_SMARTCARD_ENABLE_IT()
      • +
      • __SMARTCARD_DISABLE_IT() + by + __HAL_SMARTCARD_DISABLE_IT()
      • +
      • __SMARTCARD_DMA_REQUEST_ENABLE() + by + __HAL_SMARTCARD_DMA_REQUEST_ENABLE()
      • +
      • __SMARTCARD_DMA_REQUEST_DISABLE() + by + __HAL_SMARTCARD_DMA_REQUEST_DISABLE()
      • +
      +
    • Rename + literals: remove "D" from + "DISABLED" and "ENABLED"
    • +
        +
      • SMARTCARD_NACK_ENABLED by + + + + + SMARTCARD_NACK_ENABLE
      • +
      • SMARTCARD_NACK_DISABLED by SMARTCARD_NACK_DISABLE
      • +
      +
    • Add new user + macros to manage the sample + method feature
    • +
        +
      • __HAL_SMARTCARD_ONE_BIT_SAMPLE_ENABLE()
      • +
      • __HAL_SMARTCARD_ONE_BIT_SAMPLE_DISABLE()
      • +
      +
    • Add use + of tmpreg + variable in + __HAL_SMARTCARD_CLEAR_PEFLAG() + macro for compliancy with + C++
    • +
    • HAL_SMARTCARD_Transmit_DMA() update to + follow the + right procedure + "Transmission using DMA"  + in the reference manual
    • +
        +
      • Add clear + the TC flag in the SR + register before enabling the + DMA transmit + request
      • +
      +
    +
  • HAL + + + + TIM update
  • +
      +
    • Add + TIM_CHANNEL_ALL as possible + value for all Encoder + Start/Stop APIs Description
    • +
    • HAL_TIM_OC_ConfigChannel() remove call + to IS_TIM_FAST_STATE() assert + macro
    • +
    • HAL_TIM_PWM_ConfigChannel() add a call + to IS_TIM_FAST_STATE() assert + macro to check the OCFastMode + parameter
    • +
    • HAL_TIM_DMADelayPulseCplt() Update to + set the TIM Channel before to + call  HAL_TIM_PWM_PulseFinishedCallback()
    • +
    • HAL_TIM_DMACaptureCplt() update to + set the TIM Channel before to + call  HAL_TIM_IC_CaptureCallback()
    • +
    • TIM_ICx_ConfigChannel() update + to fix Timer CCMR1 register + corruption when setting ICFilter + parameter
    • +
    • HAL_TIM_DMABurst_WriteStop()/HAL_TIM_DMABurst_ReadStop() + update to abort the DMA + transfer for the specifc + TIM channel
    • +
    • Add new + function for TIM Slave + configuration in IT mode: + HAL_TIM_SlaveConfigSynchronization_IT(
    • +
    • HAL_TIMEx_ConfigBreakDeadTime() add an + assert check on Break & DeadTime + parameters values
    • +
    • HAL_TIMEx_OCN_Start_IT() add the + enable of Break Interrupt for + all output modes
    • +
    • Add new + macros to ENABLE/DISABLE URS + bit in TIM CR1 register:
    • +
        +
      • __HAL_TIM_URS_ENABLE()
      • +
      • __HAL_TIM_URS_DISABLE()
      • +
      +
    • Add new macro + for TIM Edge modification: + __HAL_TIM_SET_CAPTUREPOLARITY()
    • +
    +
  • HAL + + + + UART update
  • +
      +
    • Add IS_LIN_WORD_LENGTH() + and + IS_LIN_OVERSAMPLING()  + macros: to check respectively + WordLength + and OverSampling + parameters in LIN mode
    • +
    • DMA transmit + process; the code has been + updated to avoid waiting on TC + flag under DMA ISR, UART TC + interrupt is used instead. + Below the update to be done on + user application:
    • +
        +
      • Configure + and enable the USART IRQ in + HAL_UART_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, USARTx_IRQHandler() + function: add a call to HAL_UART_IRQHandler() + + + + function
      • +
      +
    • IT transmit + process; the code has been + updated to avoid waiting on TC + flag under UART ISR, UART + TC interrupt is used instead. + No impact on user application
    • +
    • Rename + macros:
    • +
        +
      • __HAL_UART_ONEBIT_ENABLE() + by + __HAL_UART_ONE_BIT_SAMPLE_ENABLE()
      • +
      • __HAL_UART_ONEBIT_DISABLE() + by + __HAL_UART_ONE_BIT_SAMPLE_DISABLE()
      • +
      +
    • Rename + literals:
    • +
        +
      • UART_WAKEUPMETHODE_IDLELINE by + + + + + UART_WAKEUPMETHOD_IDLELINE
      • +
      • UART_WAKEUPMETHODE_ADDRESSMARK by +UART_WAKEUPMETHOD_ADDRESSMARK
      • +
      +
    • Add use + of tmpreg + variable in __HAL_UART_CLEAR_PEFLAG() + macro for compliancy with + C++
    • +
    • HAL_UART_Transmit_DMA() update to + follow the right procedure + "Transmission using DMA" in + the reference manual
    • +
        +
      • Add clear + the TC flag in the SR + register before enabling the + DMA transmit + request
      • +
      +
    +
  • HAL + + + + USART update
  • +
      +
    • DMA transmit + process; the code has been + updated to avoid waiting on TC + flag under DMA ISR, USART TC + interrupt is used instead. + Below the update to be done on + user application:
    • +
        +
      • Configure + and enable the USART IRQ in + HAL_USART_MspInit() + function
      • +
      • In + stm32f4xx_it.c file, USARTx_IRQHandler() + function: add a call to HAL_USART_IRQHandler() + + + + + function
      • +
      +
    • IT transmit + process; the code has been + updated to avoid waiting on TC + flag under USART ISR, + USART TC interrupt is used + instead. No impact on user + application
    • +
    • HAL_USART_Init() update + to enable the USART + oversampling by 8 by default + in order to reach max USART + frequencies
    • +
    • USART_DMAReceiveCplt() update + to set the new USART state + after checking on the + old state
    • +
    • HAL_USART_Transmit_DMA()/HAL_USART_TransmitReceive_DMA() + update to + follow the + right procedure + "Transmission using DMA"  + in the reference manual
    • +
        +
      • Add clear + the TC flag in the SR + register before enabling the + DMA transmit + request
      • +
      +
    • Rename + macros:
    • +
        +
      • __USART_ENABLE() + by __HAL_USART_ENABLE()
      • +
      • __USART_DISABLE() + by __HAL_USART_DISABLE()
      • +
      • __USART_ENABLE_IT() + by __HAL_USART_ENABLE_IT()
      • +
      • __USART_DISABLE_IT() + by __HAL_USART_DISABLE_IT()
      • +
      +
    • Rename + literals: remove "D" from + "DISABLED" and "ENABLED"
    • +
        +
      • USART_CLOCK_DISABLED by + + + + + USART_CLOCK_DISABLE
      • +
      • USART_CLOCK_ENABLED by + + + + + USART_CLOCK_ENABLE
      • +
      • USARTNACK_ENABLED + + + + by USART_NACK_ENABLE
      • +
      • USARTNACK_DISABLED + + + + by USART_NACK_DISABLE
      • +
      +
    • Add new user + macros to manage the sample + method feature
    • +
        +
      • __HAL_USART_ONE_BIT_SAMPLE_ENABLE()
      • +
      • __HAL_USART_ONE_BIT_SAMPLE_DISABLE()
      • +
      +
    • Add use + of tmpreg + variable in __HAL_USART_CLEAR_PEFLAG() + macro for compliancy with + C++
    • +
    +
  • HAL + + + + WWDG update
  • +
      +
    • Add new + parameter in + __HAL_WWDG_ENABLE_IT() + macro
    • +
    • Add new + macros to manage WWDG IT & + correction:
    • +
        +
      • __HAL_WWDG_DISABLE()
      • +
      • __HAL_WWDG_DISABLE_IT()
      • +
      • __HAL_WWDG_GET_IT()
      • +
      • __HAL_WWDG_GET_IT_SOURCE()
      • +
      +
    +
+

V1.1.0 + + + + / 19-June-2014

+

Main Changes

+
    +
  • Add + support of STM32F411xE devices
  • +
+
    +
  • HAL + + + + generic + update
  • +
      +
    • Enhance HAL + delay and time base implementation
    • +
        +
      • Systick timer is + used by default as source of + time base, but user can + eventually implement his + proper time base source (a general + + + + purpose + timer for example or other + time source)
      • +
      • Functions + affecting time base + configurations are declared + as __Weak to make override + possible in case of other + implementations in user + file, for more details + please refer to HAL_TimeBase + example
      • +
      +
    • Fix flag + clear procedure: use atomic + write operation "=" instead of + ready-modify-write operation + "|=" or "&="
    • +
    • Fix on + Timeout management, Timeout + value set to 0 passed to API + automatically exits the + function after checking the + flag without any wait
    • +
    • Common update + for the following + communication peripherals: + SPI, UART, USART and IRDA
    • +
        +
      • Add DMA + circular mode support
      • +
      • Remove lock + from recursive process
      • +
      +
    • Add new macro + __HAL_RESET_HANDLE_STATE to + reset a given handle state
    • +
    • Add a new + attribute for functions + executed from internal SRAM + and depending from + Compiler implementation
    • +
    • When USE_RTOS + == 1 (in + stm32l0xx_hal_conf.h), the + __HAL_LOCK() + is not defined instead of + being defined empty
    • +
    • Miscellaneous + comments and formatting update
    • +
    • stm32f4xx_hal_conf_template.h
    • +
        +
      • Add a new + define for LSI default value + LSI_VALUE
      • +
      • Add a new + define for LSE default value + LSE_VALUE
      • +
      • Add a new + define for Tick interrupt + priority TICK_INT_PRIORITY + (needed for the enhanced + time base implementation)
      • +
      +
    • Important + + + + + Note: + aliases has been added for any + API naming change, to keep + compatibility with previous version
    • +
    +
  • HAL + + + + GPIO update
  • +
+
    +
      +
    • Add a new + macro __HAL_GPIO_EXTI_GENERATE_SWIT() + to manage the generation of + software interrupt on selected + EXTI line
    • +
    • HAL_GPIO_Init(): use + temporary variable when + modifying the registers, to + avoid unexpected transition in + the GPIO pin configuration
    • +
    • Remove + IS_GET_GPIO_PIN macro
    • +
    • Add a new + function HAL_GPIO_LockPin()
    • +
    • Private Macro + __HAL_GET_GPIO_SOURCE renamed + into GET_GPIO_SOURCE
    • +
    • Add the + support of STM32F411xx devices + + + + + : add the + new Alternate functions values + related to new remap added for + SPI, USART, I2C
    • +
    • Update the + following HAL GPIO macros + description: rename EXTI_Linex + by GPIO_PIN_x
    • +
        +
      • __HAL_GPIO_EXTI_CLEAR_IT()
      • +
      • __HAL_GPIO_EXTI_GET_IT()
      • +
      • __HAL_GPIO_EXTI_CLEAR_FLAG()
      • +
      • __HAL_GPIO_EXTI_GET_FLAG()
      • +
      +
    +
+

§  + + + + + HAL DMA update

+
    +
      +
    • Fix in HAL_DMA_PollForTransfer() + to:
    • +
        +
      • set DMA + error code in case of + HAL_ERROR status
      • +
      • set HAL + Unlock before DMA state update
      • +
      +
    +
+

§  + + + + + HAL DMA2D + update

+
    +
      +
    • Add + configuration of source + address in case of A8 or A4 + M2M_PFC DMA2D mode
    • +
    +
  • HAL + + + + FLASH update
  • +
+
    +
      +
    • Functions + reorganization update, + depending on the features + supported by each STM32F4 device
    • +
    • Add new + driver + (stm32f4xx_hal_flash_ramfunc.h/.c) + to manage function executed + from RAM, these functions are + available only for STM32F411xx + Devices
    • +
        +
      • FLASH_StopFlashInterfaceClk()  : + Stop the flash interface + while System Run
      • +
      • FLASH_StartFlashInterfaceClk() : Stop the + flash interface while System + Run
      • +
      • FLASH_EnableFlashSleepMode() : Enable + the flash sleep while System + Run
      • +
      • FLASH_DisableFlashSleepMode() :  + Disable the flash sleep + while System Run
      • +
      +
    +
+
    +
  • HAL + + + + PWR update
  • +
+
    +
      +
    • HAL_PWR_PVDConfig(): add clear + of the EXTI trigger before new + configuration
    • +
    • Fix in HAL_PWR_EnterSTANDBYMode() + to not clear Wakeup flag + (WUF), which need to be + cleared at application level + before to call this function
    • +
    • HAL_PWR_EnterSLEEPMode()
    • +
        +
      • Remove + disable and enable of SysTick + Timer
      • +
      • Update + usage of __WFE() + in low power entry function: + if there is a pending event, + calling __WFE() will not + enter the CortexM4 core to + sleep mode. The solution is + to made the call below; the + first __WFE() + is always ignored and clears + the event if one was already + pending, the second is + always applied
      • +
      +
    +
+
+

__SEV()
+
__WFE()
+
__WFE()

+
+
    +
      +
    • Add new macro + for software event generation + __HAL_PVD_EXTI_GENERATE_SWIT()
    • +
    • Remove the + following defines form Generic + driver and add them under + extension driver because they + are only used within extension + functions.
    • +
        +
      • CR_FPDS_BB: + used within HAL_PWREx_EnableFlashPowerDown() + function
      • +
      • CSR_BRE_BB: + used within HAL_PWREx_EnableBkUpReg() + function
      • +
      +
    • Add the + support of STM32F411xx devices + add the define STM32F411xE
    • +
        +
      • For + STM32F401xC, STM32F401xE and + STM32F411xE devices add the + following functions used to + enable or disable the low + voltage mode for regulators
      • +
      +
    +
+
    +
      +
        +
          +
        • HAL_PWREx_EnableMainRegulatorLowVoltage()
        • +
        • HAL_PWREx_DisableMainRegulatorLowVoltage()
        • +
        • HAL_PWREx_EnableLowRegulatorLowVoltage()
        • +
        • HAL_PWREx_DisableLowRegulatorLowVoltage()
        • +
        +
      +
    • For + STM32F42xxx/43xxx devices, add + a new function for Under + Driver management as the macro + already added for this mode is + not sufficient: HAL_PWREx_EnterUnderDriveSTOPMode()
    • +
    +
+
    +
  • HAL + + + + RCC update
  • +
      +
    • In HAL_RCC_ClockConfig() + function: update the AHB clock + divider before clock switch to + new source
    • +
    • Allow to + calibrate the HSI when it is + used as system clock source
    • +
    • Rename the + following macros
    • +
        +
      • __OTGFS_FORCE_RESET + + + + ()  by + __USB_OTG_FS_FORCE_RESET()
      • +
      • __OTGFS_RELEASE_RESET + + + + ()  by  +__USB_OTG_FS_RELEASE_RESET()
      • +
      • __OTGFS_CLK_SLEEP_ENABLE + + + + + ()  by  +__USB_OTG_FS_CLK_SLEEP_ENABLE()
      • +
      • __OTGFS_CLK_SLEEP_DISABLE + + + + + () by  __USB_OTG_FS_CLK_SLEEP_DISABLE()
      • +
      +
    +
+

 

+
    +
      +
    • Add new field + PLLI2SM in + RCC_PLLI2SInitTypeDef + structure, this division + factor is added for PLLI2S VCO + input clock only STM32F411xE + devices => the FW + compatibility is broken vs. + STM32F401xx devices
    • +
    • Update HAL_RCCEx_PeriphCLKConfig() + and  HAL_RCCEx_GetPeriphCLKConfig()  + + + + + functions to support the new + PLLI2SM
    • +
    • Add new + function to manage the new LSE + mode + + + + + : HAL_RCCEx_SelectLSEMode()
    • +
    • Reorganize + the macros depending from + Part number used and make them + more clear
    • +
    +
+

§  HAL + + + + UART update

+
    +
      +
    • Add new + macros to control CTS and RTS
    • +
    • Add specific + macros to manage the flags + cleared only by a software sequence
    • +
        +
      • __HAL_UART_CLEAR_PEFLAG()
      • +
      • __HAL_UART_CLEAR_FEFLAG()
      • +
      • __HAL_UART_CLEAR_NEFLAG()
      • +
      • __HAL_UART_CLEAR_OREFLAG()
      • +
      • __HAL_UART_CLEAR_IDLEFLAG()
      • +
      +
    • Add several + enhancements without affecting + the driver functionalities +
    • +
        +
      • Remove the + check on RXNE set after + reading the Data in the DR + register
      • +
      • Update the + transmit processes to use + TXE instead of TC
      • +
      • Update HAL_UART_Transmit_IT() + to enable UART_IT_TXE + instead of UART_IT_TC
      • +
      +
    +
+

§  + + + + + HAL USART + update

+
    +
      +
    • Add specific + macros to manage the flags + cleared only by a software sequence
    • +
        +
      • __HAL_USART_CLEAR_PEFLAG()
      • +
      • __HAL_USART_CLEAR_FEFLAG()
      • +
      • __HAL_USART_CLEAR_NEFLAG()
      • +
      • __HAL_USART_CLEAR_OREFLAG()
      • +
      • __HAL_USART_CLEAR_IDLEFLAG()
      • +
      +
    • Update HAL_USART_Transmit_IT() + to enable USART_IT_TXE + instead of USART_IT_TC
    • +
    +
+

§  + + + + + HAL IRDA update

+
    +
      +
    • Add specific + macros to manage the flags + cleared only by a software sequence
    • +
        +
      • __HAL_IRDA_CLEAR_PEFLAG()
      • +
      • __HAL_ + IRDA _CLEAR_FEFLAG()
      • +
      • __HAL_ + IRDA _CLEAR_NEFLAG()
      • +
      • __HAL_ + IRDA _CLEAR_OREFLAG()
      • +
      • __HAL_ + IRDA _CLEAR_IDLEFLAG()
      • +
      +
    • Add several + enhancements without affecting + the driver functionalities
    • +
    +
+
    +
      +
        +
      • Remove the + check on RXNE set after + reading the Data in the DR + register
      • +
      • Update HAL_IRDA_Transmit_IT() + to enable IRDA_IT_TXE + instead of IRDA_IT_TC
      • +
      +
    • Add the + following APIs used within DMA + process +
    • +
        +
      • HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef + *hirda);
      • +
      • HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef + *hirda);
      • +
      • HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef + *hirda); +
      • +
      • void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef + *hirda);
      • +
      • void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef + *hirda);
      • +
      +
    +
+

§  + + + + + HAL SMARTCARD + update

+
    +
      +
    • Add specific + macros to manage the flags + cleared only by a software sequence
    • +
        +
      • __HAL_SMARTCARD_CLEAR_PEFLAG()
      • +
      • __HAL_SMARTCARD_CLEAR_FEFLAG()
      • +
      • __HAL_SMARTCARD_CLEAR_NEFLAG()
      • +
      • __HAL_SMARTCARD_CLEAR_OREFLAG()
      • +
      • __HAL_SMARTCARD_CLEAR_IDLEFLAG()
      • +
      +
    • Add several + enhancements without affecting + the driver functionalities
    • +
        +
      • Add a new + state HAL_SMARTCARD_STATE_BUSY_TX_RX + and all processes has been + updated accordingly
      • +
      • Update HAL_SMARTCARD_Transmit_IT() + to enable SMARTCARD_IT_TXE + instead of SMARTCARD_IT_TC
      • +
      +
    +
+
    +
  • HAL + + + + SPI update
  • +
      +
    • Bugs fix
    • +
        +
      • SPI + interface is used in + synchronous polling mode: at + high clock rates like SPI prescaler + 2 and 4, calling
        + HAL_SPI_TransmitReceive() + returns with error + HAL_TIMEOUT
        +
      • +
      • HAL_SPI_TransmitReceive_DMA() does not + clean up the TX DMA, so any + subsequent SPI calls return + the DMA error
      • +
      • HAL_SPI_Transmit_DMA() is failing + when data size is equal to 1 + byte +
      • +
      +
    • Add the + following APIs used within the + DMA process
    • +
    +
+
    +
      +
        +
      • HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef + *hspi);
      • +
      • HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef + *hspi);
      • +
      • HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef + *hspi);
      • +
      • void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef + *hspi);
      • +
      • void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef + *hspi);
      • +
      • void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef + *hspi);
      • +
      +
    +
+
    +
  • HAL + + + + RNG update
  • +
      +
        +
      • Add a + conditional define to make + this driver visible for all + STM32F4xx devices except + STM32F401xx and STM32F411xx + Devices.
      • +
      +
    +
  • HAL + + + + CRC update
  • +
      +
        +
      • These + macros are added to + read/write the CRC IDR + register: __HAL_CRC_SET_IDR() + and __HAL_CRC_GET_IDR()
      • +
      +
    +
+
    +
  • HAL + + + + DAC update
  • +
      +
    • Enhance the + DMA channel configuration when + used with DAC
    • +
    +
  • HAL + + + + TIM update
  • +
      +
    • HAL_TIM_IRQHandler(): update to + check the input capture + channel 3 and 4 in CCMR2 + instead of CCMR1
    • +
    • __HAL_TIM_PRESCALER() + updated to use '=' instead of + '|='
    • +
    • Add the + following macro in TIM HAL + driver
    • +
        +
      • __HAL_TIM_GetCompare() +
      • +
      • __HAL_TIM_GetCounter() +
      • +
      • __HAL_TIM_GetAutoreload() +
      • +
      • __HAL_TIM_GetClockDivision() +
      • +
      • __HAL_TIM_GetICPrescaler()
      • +
      +
    +
  • HAL + + + + SDMMC update
  • +
+
    +
      +
    • Use of CMSIS + constants instead of magic values
    • +
    • Miscellaneous + update in functions internal + coding
    • +
    +
  • HAL + + + + NAND update
  • +
      +
    • Fix + + + + issue of macros returning + wrong address for NAND blocks
    • +
    • Fix + + + + issue for read/write NAND + page/spare area
    • +
    +
  • HAL + + + + NOR update
  • +
      +
    • Add + + + + the NOR address bank macro + used within the API
    • +
    • Update + + + + NOR API implementation to + avoid the use of NOR address + bank hard coded
    • +
    +
  • HAL + + + + HCD update
  • +
      +
    • HCD_StateTypeDef structure + members renamed
    • +
    • These macro are renamed
    • +
        +
      • __HAL_GET_FLAG(__HANDLE__, + + + + + __INTERRUPT__)    + + + + by + __HAL_HCD_GET_FLAG(__HANDLE__, + __INTERRUPT__)
      • +
      • __HAL_CLEAR_FLAG(__HANDLE__, + + + + + __INTERRUPT__) by + __HAL_HCD_CLEAR_FLAG(__HANDLE__, + __INTERRUPT__) 
      • +
      • __HAL_IS_INVALID_INTERRUPT(__HANDLE__)  + + + + + by + __HAL_HCD_IS_INVALID_INTERRUPT(__HANDLE__)  +
      • +
      +
    +
  • HAL + + + + PCD update
  • +
      +
    • HAL_PCD_SetTxFiFo() and HAL_PCD_SetRxFiFo() + + + + + renamed into HAL_PCDEx_SetTxFiFo() + + + + + and HAL_PCDEx_SetRxFiFo() + + + + + and moved to the extension + files + stm32f4xx_hal_pcd_ex.h/.c
    • +
    • PCD_StateTypeDef structure + members renamed
    • +
    • Fix incorrect + masking of TxFIFOEmpty
    • +
    • stm32f4xx_ll_usb.c: + + + + fix issue in HS mode
    • +
    • New macros added
    • +
        +
      • __HAL_PCD_IS_PHY_SUSPENDED()
      • +
      • __HAL_USB_HS_EXTI_GENERATE_SWIT()
      • +
      • __HAL_USB_FS_EXTI_GENERATE_SWIT()
      • +
      +
    • These macro are renamed
    • +
        +
      • __HAL_GET_FLAG(__HANDLE__, + + + + + __INTERRUPT__)    + + + + by + __HAL_PCD_GET_FLAG(__HANDLE__, + __INTERRUPT__)
      • +
      • __HAL_CLEAR_FLAG(__HANDLE__, + + + + + __INTERRUPT__) by + __HAL_PCD_CLEAR_FLAG(__HANDLE__, + __INTERRUPT__) 
      • +
      • __HAL_IS_INVALID_INTERRUPT(__HANDLE__)  + + + + + by + __HAL_PCD_IS_INVALID_INTERRUPT(__HANDLE__)  +
      • +
      • __HAL_PCD_UNGATE_CLOCK(__HANDLE__) + + + + + by + __HAL_PCD_UNGATE_PHYCLOCK(__HANDLE__)
      • +
      • __HAL_PCD_GATE_CLOCK(__HANDLE__) + + + + + by + __HAL_PCD_GATE_PHYCLOCK(__HANDLE__)
      • +
      +
    +
  • HAL + + + + ETH update
  • +
      +
    • Update HAL_ETH_GetReceivedFrame_IT() + function to return HAL_ERROR + if the received packet is not + complete
    • +
    • Use HAL_Delay() + instead of counting loop
    • +
    •  __HAL_ETH_MAC_CLEAR_FLAG() + macro is removed: the MACSR + register is read only
    • +
    • Add the + following macros used to Wake + up the device from STOP mode + by Ethernet event + + + + :
    • +
        +
      • __HAL_ETH_EXTI_ENABLE_IT()
      • +
      • __HAL_ETH_EXTI_DISABLE_IT()
      • +
      • __HAL_ETH_EXTI_GET_FLAG()
      • +
      • __HAL_ETH_EXTI_CLEAR_FLAG()
      • +
      • __HAL_ETH_EXTI_SET_RISING_EGDE_TRIGGER()
      • +
      • __HAL_ETH_EXTI_SET_FALLING_EGDE_TRIGGER()
      • +
      • __HAL_ETH_EXTI_SET_FALLINGRISING_TRIGGER()
      • +
      +
    +
  • HAL + + + + WWDG update
  • +
      +
    • Update macro + parameters to use underscore: + __XXX__
    • +
    • Use of CMSIS + constants instead of magic values
    • +
    • Use + MODIFY_REG macro in HAL_WWDG_Init()
    • +
    • Add + IS_WWDG_ALL_INSTANCE in HAL_WWDG_Init() + and HAL_WWDG_DeInit()
    • +
    +
  • HAL + + + + IWDG update
  • +
      +
    • Use WRITE_REG + instead of SET_BIT for all + IWDG macros
    • +
    • __HAL_IWDG_CLEAR_FLAG + + + + + removed: no IWDG flag cleared + by access to SR register
    • +
    • Use + MODIFY_REG macro in HAL_IWDG_Init()
    • +
    • Add + IS_IWDG_ALL_INSTANCE in HAL_IWDG_Init()Add + + + + + the following macros used to + Wake
    • +
    +
+

V1.0.0 + + + + / 18-February-2014

+

Main Changes

+
    +
  • First + + + + official release 
  • +
+

+

For + + + + + complete documentation on STM32 + Microcontrollers visit www.st.com/STM32

+
+

 

+
+
+

+
+
+

 

+
+
+ \ No newline at end of file diff --git a/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c b/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c new file mode 100644 index 0000000..e175142 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_can.c @@ -0,0 +1,1679 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_can.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the Controller Area Network (CAN) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Error 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 + ============================================================================== + ##### User NOTE ##### + ============================================================================== + [..] + (#) This HAL CAN driver is deprecated, it contains some CAN Tx/Rx FIFO management limitations. + Another HAL CAN driver version has been designed with new API's, to fix these limitations. + + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Enable the CAN controller interface clock using + __HAL_RCC_CAN1_CLK_ENABLE() for CAN1, __HAL_RCC_CAN2_CLK_ENABLE() for CAN2 + and __HAL_RCC_CAN3_CLK_ENABLE() for CAN3 + -@- In case you are using CAN2 only, you have to enable the CAN1 clock. + + (#) CAN pins configuration + (++) Enable the clock for the CAN GPIOs using the following function: + __GPIOx_CLK_ENABLE() + (++) Connect and configure the involved CAN pins to AF9 using the + following function HAL_GPIO_Init() + + (#) Initialize and configure the CAN using CAN_Init() function. + + (#) Transmit the desired CAN frame using HAL_CAN_Transmit() function. + + (#) Or transmit the desired CAN frame using HAL_CAN_Transmit_IT() function. + + (#) Receive a CAN frame using HAL_CAN_Receive() function. + + (#) Or receive a CAN frame using HAL_CAN_Receive_IT() function. + + *** Polling mode IO operation *** + ================================= + [..] + (+) Start the CAN peripheral transmission and wait the end of this operation + using HAL_CAN_Transmit(), at this stage user can specify the value of timeout + according to his end application + (+) Start the CAN peripheral reception and wait the end of this operation + using HAL_CAN_Receive(), at this stage user can specify the value of timeout + according to his end application + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Start the CAN peripheral transmission using HAL_CAN_Transmit_IT() + (+) Start the CAN peripheral reception using HAL_CAN_Receive_IT() + (+) Use HAL_CAN_IRQHandler() called under the used CAN Interrupt subroutine + (+) At CAN end of transmission HAL_CAN_TxCpltCallback() function is executed and user can + add his own code by customization of function pointer HAL_CAN_TxCpltCallback + (+) In case of CAN Error, HAL_CAN_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_CAN_ErrorCallback + + *** CAN HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in CAN HAL driver. + + (+) __HAL_CAN_ENABLE_IT: Enable the specified CAN interrupts + (+) __HAL_CAN_DISABLE_IT: Disable the specified CAN interrupts + (+) __HAL_CAN_GET_IT_SOURCE: Check if the specified CAN interrupt source is enabled or disabled + (+) __HAL_CAN_CLEAR_FLAG: Clear the CAN's pending flags + (+) __HAL_CAN_GET_FLAG: Get the selected CAN's flag status + + [..] + (@) You can refer to the CAN Legacy HAL driver header file for more useful macros + + @endverbatim + + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup CAN CAN + * @brief CAN driver modules + * @{ + */ + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED + +#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ + defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) ||\ + defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||\ + defined(STM32F423xx) + +#ifdef HAL_CAN_MODULE_ENABLED +/* Select HAL CAN module in stm32f4xx_hal_conf.h file: + (#) HAL_CAN_MODULE_ENABLED for new HAL CAN driver fixing FIFO limitations + (#) HAL_CAN_LEGACY_MODULE_ENABLED for legacy HAL CAN driver */ +#error 'The HAL CAN driver cannot be used with its legacy, Please ensure to enable only one HAL CAN module at once in stm32f4xx_hal_conf.h file' +#endif /* HAL_CAN_MODULE_ENABLED */ + +#warning 'Legacy HAL CAN driver is enabled! It can be used with known limitations, refer to the release notes. However it is recommended to use rather the new HAL CAN driver' + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup CAN_Private_Constants + * @{ + */ +#define CAN_TIMEOUT_VALUE 10U +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup CAN_Private_Functions + * @{ + */ +static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber); +static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup CAN_Exported_Functions CAN Exported Functions + * @{ + */ + +/** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de-initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the CAN. + (+) De-initialize the CAN. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_InitStruct. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan) +{ + uint32_t InitStatus = CAN_INITSTATUS_FAILED; + uint32_t tickstart = 0U; + + /* Check CAN handle */ + if(hcan == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TTCM)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ABOM)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AWUM)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.NART)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.RFLM)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TXFP)); + assert_param(IS_CAN_MODE(hcan->Init.Mode)); + assert_param(IS_CAN_SJW(hcan->Init.SJW)); + assert_param(IS_CAN_BS1(hcan->Init.BS1)); + assert_param(IS_CAN_BS2(hcan->Init.BS2)); + assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler)); + + + if(hcan->State == HAL_CAN_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcan->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_CAN_MspInit(hcan); + } + + /* Initialize the CAN state*/ + hcan->State = HAL_CAN_STATE_BUSY; + + /* Exit from sleep mode */ + hcan->Instance->MCR &= (~(uint32_t)CAN_MCR_SLEEP); + + /* Request initialisation */ + hcan->Instance->MCR |= CAN_MCR_INRQ ; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the acknowledge */ + while((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) + { + if((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE) + { + hcan->State= HAL_CAN_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + + /* Check acknowledge */ + if ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) + { + /* Set the time triggered communication mode */ + if (hcan->Init.TTCM == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_TTCM; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TTCM; + } + + /* Set the automatic bus-off management */ + if (hcan->Init.ABOM == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_ABOM; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_ABOM; + } + + /* Set the automatic wake-up mode */ + if (hcan->Init.AWUM == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_AWUM; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_AWUM; + } + + /* Set the no automatic retransmission */ + if (hcan->Init.NART == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_NART; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_NART; + } + + /* Set the receive FIFO locked mode */ + if (hcan->Init.RFLM == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_RFLM; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_RFLM; + } + + /* Set the transmit FIFO priority */ + if (hcan->Init.TXFP == ENABLE) + { + hcan->Instance->MCR |= CAN_MCR_TXFP; + } + else + { + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TXFP; + } + + /* Set the bit timing register */ + hcan->Instance->BTR = (uint32_t)((uint32_t)hcan->Init.Mode) | \ + ((uint32_t)hcan->Init.SJW) | \ + ((uint32_t)hcan->Init.BS1) | \ + ((uint32_t)hcan->Init.BS2) | \ + ((uint32_t)hcan->Init.Prescaler - 1U); + + /* Request leave initialisation */ + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_INRQ; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the acknowledge */ + while((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) + { + if((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE) + { + hcan->State= HAL_CAN_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + + /* Check acknowledged */ + if ((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) + { + InitStatus = CAN_INITSTATUS_SUCCESS; + } + } + + if(InitStatus == CAN_INITSTATUS_SUCCESS) + { + /* Set CAN error code to none */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Initialize the CAN state */ + hcan->State = HAL_CAN_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Initialize the CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Configures the CAN reception filter according to the specified + * parameters in the CAN_FilterInitStruct. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param sFilterConfig pointer to a CAN_FilterConfTypeDef structure that + * contains the filter configuration information. + * @retval None + */ +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig) +{ + uint32_t filternbrbitpos = 0U; + CAN_TypeDef *can_ip; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* Check the parameters */ + assert_param(IS_CAN_FILTER_NUMBER(sFilterConfig->FilterNumber)); + assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode)); + assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale)); + assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment)); + assert_param(IS_FUNCTIONAL_STATE(sFilterConfig->FilterActivation)); + assert_param(IS_CAN_BANKNUMBER(sFilterConfig->BankNumber)); + + filternbrbitpos = 1U << sFilterConfig->FilterNumber; +#if defined (CAN3) + /* Check the CAN instance */ + if(hcan->Instance == CAN3) + { + can_ip = CAN3; + } + else + { + can_ip = CAN1; + } +#else + can_ip = CAN1; +#endif + + /* Initialisation mode for the filter */ + can_ip->FMR |= (uint32_t)CAN_FMR_FINIT; + +#if defined (CAN2) + /* Select the start slave bank */ + can_ip->FMR &= ~((uint32_t)CAN_FMR_CAN2SB); + can_ip->FMR |= (uint32_t)(sFilterConfig->BankNumber << 8U); +#endif + + /* Filter Deactivation */ + can_ip->FA1R &= ~(uint32_t)filternbrbitpos; + + /* Filter Scale */ + if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT) + { + /* 16-bit scale for the filter */ + can_ip->FS1R &= ~(uint32_t)filternbrbitpos; + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterNumber].FR1 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterNumber].FR2 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh); + } + + if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT) + { + /* 32-bit scale for the filter */ + can_ip->FS1R |= filternbrbitpos; + + /* 32-bit identifier or First 32-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterNumber].FR1 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); + /* 32-bit mask or Second 32-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterNumber].FR2 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow); + } + + /* Filter Mode */ + if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK) + { + /*Id/Mask mode for the filter*/ + can_ip->FM1R &= ~(uint32_t)filternbrbitpos; + } + else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */ + { + /*Identifier list mode for the filter*/ + can_ip->FM1R |= (uint32_t)filternbrbitpos; + } + + /* Filter FIFO assignment */ + if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0) + { + /* FIFO 0 assignation for the filter */ + can_ip->FFA1R &= ~(uint32_t)filternbrbitpos; + } + + if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO1) + { + /* FIFO 1 assignation for the filter */ + can_ip->FFA1R |= (uint32_t)filternbrbitpos; + } + + /* Filter activation */ + if (sFilterConfig->FilterActivation == ENABLE) + { + can_ip->FA1R |= filternbrbitpos; + } + + /* Leave the initialisation mode for the filter */ + can_ip->FMR &= ~((uint32_t)CAN_FMR_FINIT); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Deinitializes the CANx peripheral registers to their default reset values. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan) +{ + /* Check CAN handle */ + if(hcan == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_BUSY; + + /* DeInit the low level hardware */ + HAL_CAN_MspDeInit(hcan); + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the CAN MSP. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes the CAN MSP. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Transmit a CAN frame message. + (+) Receive a CAN frame message. + (+) Enter CAN peripheral in sleep mode. + (+) Wake up the CAN peripheral from sleep mode. + +@endverbatim + * @{ + */ + +/** + * @brief Initiates and transmits a CAN frame message. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param Timeout Specify Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout) +{ + uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX; + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE)); + assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR)); + assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC)); + + if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \ + ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \ + ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)) + { + /* Process locked */ + __HAL_LOCK(hcan); + + /* Change CAN state */ + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + case(HAL_CAN_STATE_BUSY_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + } + + /* Select one empty transmit mailbox */ + if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) + { + transmitmailbox = CAN_TXMAILBOX_0; + } + else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) + { + transmitmailbox = CAN_TXMAILBOX_1; + } + else + { + transmitmailbox = CAN_TXMAILBOX_2; + } + + /* Set up the Id */ + hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ; + if (hcan->pTxMsg->IDE == CAN_ID_STD) + { + assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId)); + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \ + hcan->pTxMsg->RTR); + } + else + { + assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId)); + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \ + hcan->pTxMsg->IDE | \ + hcan->pTxMsg->RTR); + } + + /* Set up the DLC */ + hcan->pTxMsg->DLC &= (uint8_t)0x0000000F; + hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0U; + hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC; + + /* Set up the data field */ + hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) | + ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) | + ((uint32_t)hcan->pTxMsg->Data[1U] << 8U) | + ((uint32_t)hcan->pTxMsg->Data[0U])); + hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) | + ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) | + ((uint32_t)hcan->pTxMsg->Data[5U] << 8U) | + ((uint32_t)hcan->pTxMsg->Data[4U])); + /* Request transmission */ + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check End of transmission flag */ + while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox))) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hcan->State = HAL_CAN_STATE_TIMEOUT; + + __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox); + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + } + + /* Change CAN state */ + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + default: /* HAL_CAN_STATE_BUSY_TX */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Initiates and transmits a CAN frame message. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan) +{ + uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX; + + /* Check the parameters */ + assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE)); + assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR)); + assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC)); + + if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \ + ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \ + ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)) + { + /* Process Locked */ + __HAL_LOCK(hcan); + + /* Select one empty transmit mailbox */ + if((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) + { + transmitmailbox = CAN_TXMAILBOX_0; + } + else if((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) + { + transmitmailbox = CAN_TXMAILBOX_1; + } + else + { + transmitmailbox = CAN_TXMAILBOX_2; + } + + /* Set up the Id */ + hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ; + if(hcan->pTxMsg->IDE == CAN_ID_STD) + { + assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId)); + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \ + hcan->pTxMsg->RTR); + } + else + { + assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId)); + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \ + hcan->pTxMsg->IDE | \ + hcan->pTxMsg->RTR); + } + + /* Set up the DLC */ + hcan->pTxMsg->DLC &= (uint8_t)0x0000000F; + hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0U; + hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC; + + /* Set up the data field */ + hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) | + ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) | + ((uint32_t)hcan->pTxMsg->Data[1U] << 8U) | + ((uint32_t)hcan->pTxMsg->Data[0U])); + hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) | + ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) | + ((uint32_t)hcan->pTxMsg->Data[5U] << 8U) | + ((uint32_t)hcan->pTxMsg->Data[4U])); + + /* Change CAN state */ + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + case(HAL_CAN_STATE_BUSY_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + } + + /* Set CAN error code to none */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hcan); + + /* Request transmission */ + hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ; + + /* Enable Error warning, Error passive, Bus-off, + Last error and Error Interrupts */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG | + CAN_IT_EPV | + CAN_IT_BOF | + CAN_IT_LEC | + CAN_IT_ERR | + CAN_IT_TME); + } + else + { + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + /* Return function status */ + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Receives a correct CAN frame. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param FIFONumber FIFO Number value + * @param Timeout Specify Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + CanRxMsgTypeDef* pRxMsg = NULL; + + /* Check the parameters */ + assert_param(IS_CAN_FIFO(FIFONumber)); + + /* Check if CAN state is not busy for RX FIFO0 */ + if ((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) || \ + (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1))) + { + return HAL_BUSY; + } + + /* Check if CAN state is not busy for RX FIFO1 */ + if ((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1))) + { + return HAL_BUSY; + } + + /* Process locked */ + __HAL_LOCK(hcan); + + /* Change CAN state */ + if (FIFONumber == CAN_FIFO0) + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + case(HAL_CAN_STATE_BUSY_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + } + } + else /* FIFONumber == CAN_FIFO1 */ + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + case(HAL_CAN_STATE_BUSY_RX0): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + } + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check pending message */ + while(__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0U) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) + { + hcan->State = HAL_CAN_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + } + + /* Set RxMsg pointer */ + if(FIFONumber == CAN_FIFO0) + { + pRxMsg = hcan->pRxMsg; + } + else /* FIFONumber == CAN_FIFO1 */ + { + pRxMsg = hcan->pRx1Msg; + } + + /* Get the Id */ + pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR; + if (pRxMsg->IDE == CAN_ID_STD) + { + pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U); + } + else + { + pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U); + } + + pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR; + /* Get the DLC */ + pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR; + /* Get the FMI */ + pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U); + /* Get the FIFONumber */ + pRxMsg->FIFONumber = FIFONumber; + /* Get the data field */ + pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR; + pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U); + pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U); + pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U); + pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR; + pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U); + pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U); + pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U); + + /* Release the FIFO */ + if(FIFONumber == CAN_FIFO0) + { + /* Release FIFO0 */ + __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0); + } + else /* FIFONumber == CAN_FIFO1 */ + { + /* Release FIFO1 */ + __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1); + } + + /* Change CAN state */ + if (FIFONumber == CAN_FIFO0) + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + default: /* HAL_CAN_STATE_BUSY_RX0 */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + } + else /* FIFONumber == CAN_FIFO1 */ + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + default: /* HAL_CAN_STATE_BUSY_RX1 */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Receives a correct CAN frame. + * @param hcan Pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param FIFONumber Specify the FIFO number + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber) +{ + /* Check the parameters */ + assert_param(IS_CAN_FIFO(FIFONumber)); + + /* Check if CAN state is not busy for RX FIFO0 */ + if((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) || \ + (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1))) + { + return HAL_BUSY; + } + + /* Check if CAN state is not busy for RX FIFO1 */ + if((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) || \ + (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1))) + { + return HAL_BUSY; + } + + /* Process locked */ + __HAL_LOCK(hcan); + + /* Change CAN state */ + if(FIFONumber == CAN_FIFO0) + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + case(HAL_CAN_STATE_BUSY_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + } + } + else /* FIFONumber == CAN_FIFO1 */ + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + case(HAL_CAN_STATE_BUSY_RX0): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1; + break; + default: /* HAL_CAN_STATE_READY */ + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + } + } + /* Set CAN error code to none */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Enable interrupts: */ + /* - Enable Error warning Interrupt */ + /* - Enable Error passive Interrupt */ + /* - Enable Bus-off Interrupt */ + /* - Enable Last error code Interrupt */ + /* - Enable Error Interrupt */ + /* - Enable Transmit mailbox empty Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG | + CAN_IT_EPV | + CAN_IT_BOF | + CAN_IT_LEC | + CAN_IT_ERR | + CAN_IT_TME); + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + if(FIFONumber == CAN_FIFO0) + { + /* Enable FIFO 0 overrun and message pending Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0); + } + else + { + /* Enable FIFO 1 overrun and message pending Interrupt */ + __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Enters the Sleep (low power) mode. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef* hcan) +{ + uint32_t tickstart = 0U; + + /* Process locked */ + __HAL_LOCK(hcan); + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_BUSY; + + /* Request Sleep mode */ + hcan->Instance->MCR = (((hcan->Instance->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP); + + /* Sleep mode status */ + if ((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK) + { + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_ERROR; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the acknowledge */ + while((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK) + { + if((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + hcan->State = HAL_CAN_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Wakes up the CAN peripheral from sleep mode, after that the CAN peripheral + * is in the normal mode. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan) +{ + uint32_t tickstart = 0U; + + /* Process locked */ + __HAL_LOCK(hcan); + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_BUSY; + + /* Wake up request */ + hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_SLEEP; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Sleep mode status */ + while((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK) + { + if((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + hcan->State= HAL_CAN_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hcan); + return HAL_TIMEOUT; + } + } + if((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK) + { + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_ERROR; + } + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcan); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Handles CAN interrupt request + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan) +{ + uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U; + uint32_t errorcode = HAL_CAN_ERROR_NONE; + + /* Check Overrun flag for FIFO0 */ + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV0); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV0); + if(tmp1 && tmp2) + { + /* Set CAN error code to FOV0 error */ + errorcode |= HAL_CAN_ERROR_FOV0; + + /* Clear FIFO0 Overrun Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0); + } + /* Check Overrun flag for FIFO1 */ + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV1); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV1); + + if(tmp1 && tmp2) + { + /* Set CAN error code to FOV1 error */ + errorcode |= HAL_CAN_ERROR_FOV1; + + /* Clear FIFO1 Overrun Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1); + } + + /* Check End of transmission flag */ + if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME)) + { + tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0); + tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1); + tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2); + if(tmp1 || tmp2 || tmp3) + { + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK0); + tmp2 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK1); + tmp3 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK2); + /* Check Transmit success */ + if(tmp1 || tmp2 || tmp3) + { + /* Call transmit function */ + CAN_Transmit_IT(hcan); + } + else /* Transmit failure */ + { + /* Set CAN error code to TXFAIL error */ + errorcode |= HAL_CAN_ERROR_TXFAIL; + } + + /* Clear transmission status flags (RQCPx and TXOKx) */ + SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2 | \ + CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2); + } + } + + tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0); + /* Check End of reception flag for FIFO0 */ + if((tmp1 != 0U) && tmp2) + { + /* Call receive function */ + CAN_Receive_IT(hcan, CAN_FIFO0); + } + + tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1); + /* Check End of reception flag for FIFO1 */ + if((tmp1 != 0U) && tmp2) + { + /* Call receive function */ + CAN_Receive_IT(hcan, CAN_FIFO1); + } + + /* Set error code in handle */ + hcan->ErrorCode |= errorcode; + + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG); + tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); + /* Check Error Warning Flag */ + if(tmp1 && tmp2 && tmp3) + { + /* Set CAN error code to EWG error */ + hcan->ErrorCode |= HAL_CAN_ERROR_EWG; + } + + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV); + tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); + /* Check Error Passive Flag */ + if(tmp1 && tmp2 && tmp3) + { + /* Set CAN error code to EPV error */ + hcan->ErrorCode |= HAL_CAN_ERROR_EPV; + } + + tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF); + tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); + /* Check Bus-Off Flag */ + if(tmp1 && tmp2 && tmp3) + { + /* Set CAN error code to BOF error */ + hcan->ErrorCode |= HAL_CAN_ERROR_BOF; + } + + tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC); + tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC); + tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR); + /* Check Last error code Flag */ + if((!tmp1) && tmp2 && tmp3) + { + tmp1 = (hcan->Instance->ESR) & CAN_ESR_LEC; + switch(tmp1) + { + case(CAN_ESR_LEC_0): + /* Set CAN error code to STF error */ + hcan->ErrorCode |= HAL_CAN_ERROR_STF; + break; + case(CAN_ESR_LEC_1): + /* Set CAN error code to FOR error */ + hcan->ErrorCode |= HAL_CAN_ERROR_FOR; + break; + case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0): + /* Set CAN error code to ACK error */ + hcan->ErrorCode |= HAL_CAN_ERROR_ACK; + break; + case(CAN_ESR_LEC_2): + /* Set CAN error code to BR error */ + hcan->ErrorCode |= HAL_CAN_ERROR_BR; + break; + case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0): + /* Set CAN error code to BD error */ + hcan->ErrorCode |= HAL_CAN_ERROR_BD; + break; + case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1): + /* Set CAN error code to CRC error */ + hcan->ErrorCode |= HAL_CAN_ERROR_CRC; + break; + default: + break; + } + + /* Clear Last error code Flag */ + hcan->Instance->ESR &= ~(CAN_ESR_LEC); + } + + /* Call the Error call Back in case of Errors */ + if(hcan->ErrorCode != HAL_CAN_ERROR_NONE) + { + /* Clear ERRI Flag */ + hcan->Instance->MSR = CAN_MSR_ERRI; + /* Set the CAN state ready to be able to start again the process */ + hcan->State = HAL_CAN_STATE_READY; + + /* Disable interrupts: */ + /* - Disable Error warning Interrupt */ + /* - Disable Error passive Interrupt */ + /* - Disable Bus-off Interrupt */ + /* - Disable Last error code Interrupt */ + /* - Disable Error Interrupt */ + /* - Disable FIFO 0 message pending Interrupt */ + /* - Disable FIFO 0 Overrun Interrupt */ + /* - Disable FIFO 1 message pending Interrupt */ + /* - Disable FIFO 1 Overrun Interrupt */ + /* - Disable Transmit mailbox empty Interrupt */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG | + CAN_IT_EPV | + CAN_IT_BOF | + CAN_IT_LEC | + CAN_IT_ERR | + CAN_IT_FMP0| + CAN_IT_FOV0| + CAN_IT_FMP1| + CAN_IT_FOV1| + CAN_IT_TME); + + /* Call Error callback function */ + HAL_CAN_ErrorCallback(hcan); + } +} + +/** + * @brief Transmission complete callback in non blocking mode + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Transmission complete callback in non blocking mode + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Error CAN callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group3 Peripheral State and Error functions + * @brief CAN Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] + This subsection provides functions allowing to : + (+) Check the CAN state. + (+) Check CAN Errors detected during interrupt process + +@endverbatim + * @{ + */ + +/** + * @brief return the CAN state + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL state + */ +HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan) +{ + /* Return CAN state */ + return hcan->State; +} + +/** + * @brief Return the CAN error code + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval CAN Error Code + */ +uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan) +{ + return hcan->ErrorCode; +} + +/** + * @} + */ +/** + * @brief Initiates and transmits a CAN frame message. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan) +{ + /* Disable Transmit mailbox empty Interrupt */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME); + + if(hcan->State == HAL_CAN_STATE_BUSY_TX) + { + /* Disable Error warning, Error passive, Bus-off, Last error code + and Error Interrupts */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG | + CAN_IT_EPV | + CAN_IT_BOF | + CAN_IT_LEC | + CAN_IT_ERR ); + } + + /* Change CAN state */ + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1; + break; + default: /* HAL_CAN_STATE_BUSY_TX */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + + /* Transmission complete callback */ + HAL_CAN_TxCpltCallback(hcan); + + return HAL_OK; +} + +/** + * @brief Receives a correct CAN frame. + * @param hcan Pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param FIFONumber Specify the FIFO number + * @retval HAL status + * @retval None + */ +static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber) +{ + uint32_t tmp1 = 0U; + CanRxMsgTypeDef* pRxMsg = NULL; + + /* Set RxMsg pointer */ + if(FIFONumber == CAN_FIFO0) + { + pRxMsg = hcan->pRxMsg; + } + else /* FIFONumber == CAN_FIFO1 */ + { + pRxMsg = hcan->pRx1Msg; + } + + /* Get the Id */ + pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR; + if (pRxMsg->IDE == CAN_ID_STD) + { + pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U); + } + else + { + pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U); + } + + pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR; + /* Get the DLC */ + pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR; + /* Get the FIFONumber */ + pRxMsg->FIFONumber = FIFONumber; + /* Get the FMI */ + pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U); + /* Get the data field */ + pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR; + pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U); + pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U); + pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U); + pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR; + pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U); + pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U); + pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U); + /* Release the FIFO */ + /* Release FIFO0 */ + if (FIFONumber == CAN_FIFO0) + { + __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0); + + /* Disable FIFO 0 overrun and message pending Interrupt */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0); + } + /* Release FIFO1 */ + else /* FIFONumber == CAN_FIFO1 */ + { + __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1); + + /* Disable FIFO 1 overrun and message pending Interrupt */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1); + } + + tmp1 = hcan->State; + if((tmp1 == HAL_CAN_STATE_BUSY_RX0) || (tmp1 == HAL_CAN_STATE_BUSY_RX1)) + { + /* Disable Error warning, Error passive, Bus-off, Last error code + and Error Interrupts */ + __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG | + CAN_IT_EPV | + CAN_IT_BOF | + CAN_IT_LEC | + CAN_IT_ERR); + } + + /* Change CAN state */ + if (FIFONumber == CAN_FIFO0) + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX0): + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX1; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX1; + break; + default: /* HAL_CAN_STATE_BUSY_RX0 */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + } + else /* FIFONumber == CAN_FIFO1 */ + { + switch(hcan->State) + { + case(HAL_CAN_STATE_BUSY_TX_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX; + break; + case(HAL_CAN_STATE_BUSY_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_RX0; + break; + case(HAL_CAN_STATE_BUSY_TX_RX0_RX1): + hcan->State = HAL_CAN_STATE_BUSY_TX_RX0; + break; + default: /* HAL_CAN_STATE_BUSY_RX1 */ + hcan->State = HAL_CAN_STATE_READY; + break; + } + } + + /* Receive complete callback */ + HAL_CAN_RxCpltCallback(hcan); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx ||\ + STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ + +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_eth.c b/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_eth.c new file mode 100644 index 0000000..8de9453 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/Legacy/stm32f4xx_hal_eth.c @@ -0,0 +1,2307 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETHMAC_CLK_ENABLE(); + (+++) __HAL_RCC_ETHMACTX_CLK_ENABLE(); + (+++) __HAL_RCC_ETHMACRX_CLK_ENABLE(); + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pin-out + (##) Configure Ethernet NVIC interrupt (IT mode) + + (#)Initialize Ethernet DMA Descriptors in chain mode and point to allocated buffers: + (##) HAL_ETH_DMATxDescListInit(); for Transmission process + (##) HAL_ETH_DMARxDescListInit(); for Reception process + + (#)Enable MAC and DMA transmission and reception: + (##) HAL_ETH_Start(); + + (#)Prepare ETH DMA TX Descriptors and give the hand to ETH DMA to transfer + the frame to MAC TX FIFO: + (##) HAL_ETH_TransmitFrame(); + + (#)Poll for a received frame in ETH RX DMA Descriptors and get received + frame parameters + (##) HAL_ETH_GetReceivedFrame(); (should be called into an infinite loop) + + (#) Get a received frame when an ETH RX interrupt occurs: + (##) HAL_ETH_GetReceivedFrame_IT(); (called in IT mode only) + + (#) Communicate with external PHY device: + (##) Read a specific register from the PHY + HAL_ETH_ReadPHYRegister(); + (##) Write data to a specific RHY register: + HAL_ETH_WritePHYRegister(); + + (#) Configure the Ethernet MAC after ETH peripheral initialization + HAL_ETH_ConfigMAC(); all MAC parameters should be filled. + + (#) Configure the Ethernet DMA after ETH peripheral initialization + HAL_ETH_ConfigDMA(); all DMA parameters should be filled. + + -@- The PTP protocol and the DMA descriptors ring mode are not supported + in this driver +*** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function @ref HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function @ref HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) DMAErrorCallback : DMA Error Callback. + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function @ref HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + @ref HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) DMAErrorCallback : DMA Error Callback. + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples @ref HAL_ETH_TxCpltCallback(), @ref HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ @ref HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ @ref HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_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 @ref HAL_ETH_RegisterCallback() before calling @ref HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +#ifdef HAL_ETH_LEGACY_MODULE_ENABLED + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_TIMEOUT_SWRESET 500U +#define ETH_TIMEOUT_LINKED_STATE 5000U +#define ETH_TIMEOUT_AUTONEGO_COMPLETED 5000U + +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err); +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr); +static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth); +static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth); +static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth); +static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth); +static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth); +static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth); +static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth); +static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth); +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth); +static void ETH_Delay(uint32_t mdelay); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the Ethernet peripheral + (+) De-initialize the Ethernet peripheral + + @endverbatim + * @{ + */ + +/** + * @brief Initializes the Ethernet MAC and DMA according to default + * parameters. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1 = 0U, phyreg = 0U; + uint32_t hclk = 60000000U; + uint32_t tickstart = 0U; + uint32_t err = ETH_SUCCESS; + + /* Check the ETH peripheral state */ + if(heth == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_ETH_AUTONEGOTIATION(heth->Init.AutoNegotiation)); + assert_param(IS_ETH_RX_MODE(heth->Init.RxMode)); + assert_param(IS_ETH_CHECKSUM_MODE(heth->Init.ChecksumMode)); + assert_param(IS_ETH_MEDIA_INTERFACE(heth->Init.MediaInterface)); + + if(heth->State == HAL_ETH_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + heth->Lock = HAL_UNLOCKED; +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + ETH_InitCallbacksToDefault(heth); + + if(heth->MspInitCallback == NULL) + { + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + heth->MspInitCallback = HAL_ETH_MspInit; + } + heth->MspInitCallback(heth); + +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* Enable SYSCFG Clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Select MII or RMII Mode*/ + SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL); + SYSCFG->PMC |= (uint32_t)heth->Init.MediaInterface; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + (heth->Instance)->DMABMR |= ETH_DMABMR_SR; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (((heth->Instance)->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_SWRESET) + { + heth->State= HAL_ETH_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Note: The SWR is not performed if the ETH_RX_CLK or the ETH_TX_CLK are + not available, please check your external PHY or the IO configuration */ + return HAL_TIMEOUT; + } + } + + /*-------------------------------- MAC Initialization ----------------------*/ + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = (heth->Instance)->MACMIIAR; + /* Clear CSR Clock Range CR[2:0] bits */ + tmpreg1 &= ETH_MACMIIAR_CR_MASK; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if((hclk >= 20000000U)&&(hclk < 35000000U)) + { + /* CSR Clock Range between 20-35 MHz */ + tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div16; + } + else if((hclk >= 35000000U)&&(hclk < 60000000U)) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div26; + } + else if((hclk >= 60000000U)&&(hclk < 100000000U)) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div42; + } + else if((hclk >= 100000000U)&&(hclk < 150000000U)) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div62; + } + else /* ((hclk >= 150000000)&&(hclk <= 183000000)) */ + { + /* CSR Clock Range between 150-183 MHz */ + tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_Div102; + } + + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */ + (heth->Instance)->MACMIIAR = (uint32_t)tmpreg1; + + /*-------------------- PHY initialization and configuration ----------------*/ + /* Put the PHY in reset mode */ + if((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_RESET)) != HAL_OK) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + /* Set the ETH peripheral state to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return HAL_ERROR */ + return HAL_ERROR; + } + + /* Delay to assure PHY reset */ + HAL_Delay(PHY_RESET_DELAY); + + if((heth->Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* We wait for linked status */ + do + { + HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg); + + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_LINKED_STATE) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_TIMEOUT; + } + } while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS)); + + + /* Enable Auto-Negotiation */ + if((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_AUTONEGOTIATION)) != HAL_OK) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + /* Set the ETH peripheral state to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return HAL_ERROR */ + return HAL_ERROR; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until the auto-negotiation will be completed */ + do + { + HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg); + + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > ETH_TIMEOUT_AUTONEGO_COMPLETED) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_TIMEOUT; + } + + } while (((phyreg & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE)); + + /* Read the result of the auto-negotiation */ + if((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + /* Set the ETH peripheral state to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return HAL_ERROR */ + return HAL_ERROR; + } + + /* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */ + if((phyreg & PHY_DUPLEX_STATUS) != (uint32_t)RESET) + { + /* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */ + (heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX; + } + else + { + /* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */ + (heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX; + } + /* Configure the MAC with the speed fixed by the auto-negotiation process */ + if((phyreg & PHY_SPEED_STATUS) == PHY_SPEED_STATUS) + { + /* Set Ethernet speed to 10M following the auto-negotiation */ + (heth->Init).Speed = ETH_SPEED_10M; + } + else + { + /* Set Ethernet speed to 100M following the auto-negotiation */ + (heth->Init).Speed = ETH_SPEED_100M; + } + } + else /* AutoNegotiation Disable */ + { + /* Check parameters */ + assert_param(IS_ETH_SPEED(heth->Init.Speed)); + assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode)); + + /* Set MAC Speed and Duplex Mode */ + if(HAL_ETH_WritePHYRegister(heth, PHY_BCR, ((uint16_t)((heth->Init).DuplexMode >> 3U) | + (uint16_t)((heth->Init).Speed >> 1U))) != HAL_OK) + { + /* In case of write timeout */ + err = ETH_ERROR; + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + /* Set the ETH peripheral state to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return HAL_ERROR */ + return HAL_ERROR; + } + + /* Delay to assure PHY configuration */ + HAL_Delay(PHY_CONFIG_DELAY); + } + + /* Config MAC and DMA */ + ETH_MACDMAConfig(heth, err); + + /* Set ETH HAL State to Ready */ + heth->State= HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief De-Initializes the ETH peripheral. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + if(heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + heth->MspDeInitCallback(heth); +#else + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); +#endif + + /* Set ETH HAL state to Disabled */ + heth->State= HAL_ETH_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the DMA Tx descriptors in chain mode. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param DMATxDescTab Pointer to the first Tx desc list + * @param TxBuff Pointer to the first TxBuffer list + * @param TxBuffCount Number of the used Tx desc in the list + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DMATxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMATxDescTab, uint8_t *TxBuff, uint32_t TxBuffCount) +{ + uint32_t i = 0U; + ETH_DMADescTypeDef *dmatxdesc; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */ + heth->TxDesc = DMATxDescTab; + + /* Fill each DMATxDesc descriptor with the right values */ + for(i=0U; i < TxBuffCount; i++) + { + /* Get the pointer on the ith member of the Tx Desc list */ + dmatxdesc = DMATxDescTab + i; + + /* Set Second Address Chained bit */ + dmatxdesc->Status = ETH_DMATXDESC_TCH; + + /* Set Buffer1 address pointer */ + dmatxdesc->Buffer1Addr = (uint32_t)(&TxBuff[i*ETH_TX_BUF_SIZE]); + + if ((heth->Init).ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) + { + /* Set the DMA Tx descriptors checksum insertion */ + dmatxdesc->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL; + } + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if(i < (TxBuffCount-1U)) + { + /* Set next descriptor address register with next descriptor base address */ + dmatxdesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab+i+1U); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + dmatxdesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab; + } + } + + /* Set Transmit Descriptor List Address Register */ + (heth->Instance)->DMATDLAR = (uint32_t) DMATxDescTab; + + /* Set ETH HAL State to Ready */ + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param DMARxDescTab Pointer to the first Rx desc list + * @param RxBuff Pointer to the first RxBuffer list + * @param RxBuffCount Number of the used Rx desc in the list + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DMARxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount) +{ + uint32_t i = 0U; + ETH_DMADescTypeDef *DMARxDesc; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Set the Ethernet RxDesc pointer with the first one of the DMARxDescTab list */ + heth->RxDesc = DMARxDescTab; + + /* Fill each DMARxDesc descriptor with the right values */ + for(i=0U; i < RxBuffCount; i++) + { + /* Get the pointer on the ith member of the Rx Desc list */ + DMARxDesc = DMARxDescTab+i; + + /* Set Own bit of the Rx descriptor Status */ + DMARxDesc->Status = ETH_DMARXDESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE; + + /* Set Buffer1 address pointer */ + DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i*ETH_RX_BUF_SIZE]); + + if((heth->Init).RxMode == ETH_RXINTERRUPT_MODE) + { + /* Enable Ethernet DMA Rx Descriptor interrupt */ + DMARxDesc->ControlBufferSize &= ~ETH_DMARXDESC_DIC; + } + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if(i < (RxBuffCount-1U)) + { + /* Set next descriptor address register with next descriptor base address */ + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab+i+1U); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + /* Set Receive Descriptor List Address Register */ + (heth->Instance)->DMARDLAR = (uint32_t) DMARxDescTab; + + /* Set ETH HAL State to Ready */ + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(heth); + + if(heth->State == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_DMA_ERROR_CB_ID : + heth->DMAErrorCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if(heth->State == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(heth); + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callabck is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(heth); + + if(heth->State == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_DMA_ERROR_CB_ID : + heth->DMAErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if(heth->State == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(heth); + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * + @verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Transmit a frame + HAL_ETH_TransmitFrame(); + (+) Receive a frame + HAL_ETH_GetReceivedFrame(); + HAL_ETH_GetReceivedFrame_IT(); + (+) Read from an External PHY register + HAL_ETH_ReadPHYRegister(); + (+) Write to an External PHY register + HAL_ETH_WritePHYRegister(); + + @endverbatim + + * @{ + */ + +/** + * @brief Sends an Ethernet frame. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param FrameLength Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength) +{ + uint32_t bufcount = 0U, size = 0U, i = 0U; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + if (FrameLength == 0U) + { + /* Set ETH HAL state to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_ERROR; + } + + /* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */ + if(((heth->TxDesc)->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + /* OWN bit set */ + heth->State = HAL_ETH_STATE_BUSY_TX; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_ERROR; + } + + /* Get the number of needed Tx buffers for the current frame */ + if (FrameLength > ETH_TX_BUF_SIZE) + { + bufcount = FrameLength/ETH_TX_BUF_SIZE; + if (FrameLength % ETH_TX_BUF_SIZE) + { + bufcount++; + } + } + else + { + bufcount = 1U; + } + if (bufcount == 1U) + { + /* Set LAST and FIRST segment */ + heth->TxDesc->Status |=ETH_DMATXDESC_FS|ETH_DMATXDESC_LS; + /* Set frame size */ + heth->TxDesc->ControlBufferSize = (FrameLength & ETH_DMATXDESC_TBS1); + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + heth->TxDesc->Status |= ETH_DMATXDESC_OWN; + /* Point to next descriptor */ + heth->TxDesc= (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr); + } + else + { + for (i=0U; i< bufcount; i++) + { + /* Clear FIRST and LAST segment bits */ + heth->TxDesc->Status &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + + if (i == 0U) + { + /* Setting the first segment bit */ + heth->TxDesc->Status |= ETH_DMATXDESC_FS; + } + + /* Program size */ + heth->TxDesc->ControlBufferSize = (ETH_TX_BUF_SIZE & ETH_DMATXDESC_TBS1); + + if (i == (bufcount-1U)) + { + /* Setting the last segment bit */ + heth->TxDesc->Status |= ETH_DMATXDESC_LS; + size = FrameLength - (bufcount-1U)*ETH_TX_BUF_SIZE; + heth->TxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TBS1); + } + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + heth->TxDesc->Status |= ETH_DMATXDESC_OWN; + /* point to next descriptor */ + heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr); + } + } + + /* When Tx Buffer unavailable flag is set: clear it and resume transmission */ + if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + (heth->Instance)->DMASR = ETH_DMASR_TBUS; + /* Resume DMA transmission*/ + (heth->Instance)->DMATPDR = 0U; + } + + /* Set ETH HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Checks for received frames. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetReceivedFrame(ETH_HandleTypeDef *heth) +{ + uint32_t framelength = 0U; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Check the ETH state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Check if segment is not owned by DMA */ + /* (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET)) */ + if(((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET)) + { + /* Check if last segment */ + if(((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET)) + { + /* increment segment count */ + (heth->RxFrameInfos).SegCount++; + + /* Check if last segment is first segment: one segment contains the frame */ + if ((heth->RxFrameInfos).SegCount == 1U) + { + (heth->RxFrameInfos).FSRxDesc =heth->RxDesc; + } + + heth->RxFrameInfos.LSRxDesc = heth->RxDesc; + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + framelength = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U; + heth->RxFrameInfos.length = framelength; + + /* Get the address of the buffer start address */ + heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr; + /* point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*) ((heth->RxDesc)->Buffer2NextDescAddr); + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; + } + /* Check if first segment */ + else if((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET) + { + (heth->RxFrameInfos).FSRxDesc = heth->RxDesc; + (heth->RxFrameInfos).LSRxDesc = NULL; + (heth->RxFrameInfos).SegCount = 1U; + /* Point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr); + } + /* Check if intermediate segment */ + else + { + (heth->RxFrameInfos).SegCount++; + /* Point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr); + } + } + + /* Set ETH HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_ERROR; +} + +/** + * @brief Gets the Received frame in interrupt mode. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetReceivedFrame_IT(ETH_HandleTypeDef *heth) +{ + uint32_t descriptorscancounter = 0U; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set ETH HAL State to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Scan descriptors owned by CPU */ + while (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (descriptorscancounter < ETH_RXBUFNB)) + { + /* Just for security */ + descriptorscancounter++; + + /* Check if first segment in frame */ + /* ((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)) */ + if((heth->RxDesc->Status & (ETH_DMARXDESC_FS | ETH_DMARXDESC_LS)) == (uint32_t)ETH_DMARXDESC_FS) + { + heth->RxFrameInfos.FSRxDesc = heth->RxDesc; + heth->RxFrameInfos.SegCount = 1U; + /* Point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr); + } + /* Check if intermediate segment */ + /* ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)&& ((heth->RxDesc->Status & ETH_DMARXDESC_FS) == (uint32_t)RESET)) */ + else if ((heth->RxDesc->Status & (ETH_DMARXDESC_LS | ETH_DMARXDESC_FS)) == (uint32_t)RESET) + { + /* Increment segment count */ + (heth->RxFrameInfos.SegCount)++; + /* Point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*)(heth->RxDesc->Buffer2NextDescAddr); + } + /* Should be last segment */ + else + { + /* Last segment */ + heth->RxFrameInfos.LSRxDesc = heth->RxDesc; + + /* Increment segment count */ + (heth->RxFrameInfos.SegCount)++; + + /* Check if last segment is first segment: one segment contains the frame */ + if ((heth->RxFrameInfos.SegCount) == 1U) + { + heth->RxFrameInfos.FSRxDesc = heth->RxDesc; + } + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + heth->RxFrameInfos.length = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U; + + /* Get the address of the buffer start address */ + heth->RxFrameInfos.buffer =((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr; + + /* Point to next descriptor */ + heth->RxDesc = (ETH_DMADescTypeDef*) (heth->RxDesc->Buffer2NextDescAddr); + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; + } + } + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_ERROR; +} + +/** + * @brief This function handles ETH interrupt request. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + /* Frame received */ + if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_R)) + { +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_R); + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + } + /* Frame transmitted */ + else if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_T)) + { +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call resgistered Transfer complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_T); + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + } + + /* Clear the interrupt flags */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_NIS); + + /* ETH DMA Error */ + if(__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_AIS)) + { +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + heth->DMAErrorCallback(heth); +#else + /* Ethernet Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the interrupt flags */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_FLAG_AIS); + + /* Set HAL State to Ready */ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Reads a PHY register + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * PHY_BCR: Transceiver Basic Control Register, + * PHY_BSR: Transceiver Basic Status Register. + * More PHY register could be read depending on the used PHY + * @param RegValue PHY register value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t *RegValue) +{ + uint32_t tmpreg1 = 0U; + uint32_t tickstart = 0U; + + /* Check parameters */ + assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress)); + + /* Check the ETH peripheral state */ + if(heth->State == HAL_ETH_STATE_BUSY_RD) + { + return HAL_BUSY; + } + /* Set ETH HAL State to BUSY_RD */ + heth->State = HAL_ETH_STATE_BUSY_RD; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII address register value */ + tmpreg1 |=(((uint32_t)heth->Init.PhyAddress << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |=(((uint32_t)PHYReg<<6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > PHY_READ_TO) + { + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_TIMEOUT; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + /* Get MACMIIDR value */ + *RegValue = (uint16_t)(heth->Instance->MACMIIDR); + + /* Set ETH HAL State to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Writes to a PHY register. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYReg PHY register address, is the index of one of the 32 PHY register. + * This parameter can be one of the following values: + * PHY_BCR: Transceiver Control Register. + * More PHY register could be written depending on the used PHY + * @param RegValue the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t RegValue) +{ + uint32_t tmpreg1 = 0U; + uint32_t tickstart = 0U; + + /* Check parameters */ + assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress)); + + /* Check the ETH peripheral state */ + if(heth->State == HAL_ETH_STATE_BUSY_WR) + { + return HAL_BUSY; + } + /* Set ETH HAL State to BUSY_WR */ + heth->State = HAL_ETH_STATE_BUSY_WR; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII register address value */ + tmpreg1 |=(((uint32_t)heth->Init.PhyAddress<<11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |=(((uint32_t)PHYReg<<6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Give the value to the MII data register */ + heth->Instance->MACMIIDR = (uint16_t)RegValue; + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if((HAL_GetTick() - tickstart ) > PHY_WRITE_TO) + { + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + return HAL_TIMEOUT; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + /* Set ETH HAL State to READY */ + heth->State = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Enable MAC and DMA transmission and reception. + HAL_ETH_Start(); + (+) Disable MAC and DMA transmission and reception. + HAL_ETH_Stop(); + (+) Set the MAC configuration in runtime mode + HAL_ETH_ConfigMAC(); + (+) Set the DMA configuration in runtime mode + HAL_ETH_ConfigDMA(); + +@endverbatim + * @{ + */ + + /** + * @brief Enables Ethernet MAC and DMA reception/transmission + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Enable transmit state machine of the MAC for transmission on the MII */ + ETH_MACTransmissionEnable(heth); + + /* Enable receive state machine of the MAC for reception from the MII */ + ETH_MACReceptionEnable(heth); + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Start DMA transmission */ + ETH_DMATransmissionEnable(heth); + + /* Start DMA reception */ + ETH_DMAReceptionEnable(heth); + + /* Set the ETH state to READY*/ + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State = HAL_ETH_STATE_BUSY; + + /* Stop DMA transmission */ + ETH_DMATransmissionDisable(heth); + + /* Stop DMA reception */ + ETH_DMAReceptionDisable(heth); + + /* Disable receive state machine of the MAC for reception from the MII */ + ETH_MACReceptionDisable(heth); + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable transmit state machine of the MAC for transmission on the MII */ + ETH_MACTransmissionDisable(heth); + + /* Set the ETH state*/ + heth->State = HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set ETH MAC Configuration. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf MAC Configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef *macconf) +{ + uint32_t tmpreg1 = 0U; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State= HAL_ETH_STATE_BUSY; + + assert_param(IS_ETH_SPEED(heth->Init.Speed)); + assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode)); + + if (macconf != NULL) + { + /* Check the parameters */ + assert_param(IS_ETH_WATCHDOG(macconf->Watchdog)); + assert_param(IS_ETH_JABBER(macconf->Jabber)); + assert_param(IS_ETH_INTER_FRAME_GAP(macconf->InterFrameGap)); + assert_param(IS_ETH_CARRIER_SENSE(macconf->CarrierSense)); + assert_param(IS_ETH_RECEIVE_OWN(macconf->ReceiveOwn)); + assert_param(IS_ETH_LOOPBACK_MODE(macconf->LoopbackMode)); + assert_param(IS_ETH_CHECKSUM_OFFLOAD(macconf->ChecksumOffload)); + assert_param(IS_ETH_RETRY_TRANSMISSION(macconf->RetryTransmission)); + assert_param(IS_ETH_AUTOMATIC_PADCRC_STRIP(macconf->AutomaticPadCRCStrip)); + assert_param(IS_ETH_BACKOFF_LIMIT(macconf->BackOffLimit)); + assert_param(IS_ETH_DEFERRAL_CHECK(macconf->DeferralCheck)); + assert_param(IS_ETH_RECEIVE_ALL(macconf->ReceiveAll)); + assert_param(IS_ETH_SOURCE_ADDR_FILTER(macconf->SourceAddrFilter)); + assert_param(IS_ETH_CONTROL_FRAMES(macconf->PassControlFrames)); + assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(macconf->BroadcastFramesReception)); + assert_param(IS_ETH_DESTINATION_ADDR_FILTER(macconf->DestinationAddrFilter)); + assert_param(IS_ETH_PROMISCUOUS_MODE(macconf->PromiscuousMode)); + assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(macconf->MulticastFramesFilter)); + assert_param(IS_ETH_UNICAST_FRAMES_FILTER(macconf->UnicastFramesFilter)); + assert_param(IS_ETH_PAUSE_TIME(macconf->PauseTime)); + assert_param(IS_ETH_ZEROQUANTA_PAUSE(macconf->ZeroQuantaPause)); + assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(macconf->PauseLowThreshold)); + assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(macconf->UnicastPauseFrameDetect)); + assert_param(IS_ETH_RECEIVE_FLOWCONTROL(macconf->ReceiveFlowControl)); + assert_param(IS_ETH_TRANSMIT_FLOWCONTROL(macconf->TransmitFlowControl)); + assert_param(IS_ETH_VLAN_TAG_COMPARISON(macconf->VLANTagComparison)); + assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(macconf->VLANTagIdentifier)); + + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpreg1 &= ETH_MACCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(macconf->Watchdog | + macconf->Jabber | + macconf->InterFrameGap | + macconf->CarrierSense | + (heth->Init).Speed | + macconf->ReceiveOwn | + macconf->LoopbackMode | + (heth->Init).DuplexMode | + macconf->ChecksumOffload | + macconf->RetryTransmission | + macconf->AutomaticPadCRCStrip | + macconf->BackOffLimit | + macconf->DeferralCheck); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /*----------------------- ETHERNET MACFFR Configuration --------------------*/ + /* Write to ETHERNET MACFFR */ + (heth->Instance)->MACFFR = (uint32_t)(macconf->ReceiveAll | + macconf->SourceAddrFilter | + macconf->PassControlFrames | + macconf->BroadcastFramesReception | + macconf->DestinationAddrFilter | + macconf->PromiscuousMode | + macconf->MulticastFramesFilter | + macconf->UnicastFramesFilter); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFFR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFFR = tmpreg1; + + /*--------------- ETHERNET MACHTHR and MACHTLR Configuration ---------------*/ + /* Write to ETHERNET MACHTHR */ + (heth->Instance)->MACHTHR = (uint32_t)macconf->HashTableHigh; + + /* Write to ETHERNET MACHTLR */ + (heth->Instance)->MACHTLR = (uint32_t)macconf->HashTableLow; + /*----------------------- ETHERNET MACFCR Configuration --------------------*/ + + /* Get the ETHERNET MACFCR value */ + tmpreg1 = (heth->Instance)->MACFCR; + /* Clear xx bits */ + tmpreg1 &= ETH_MACFCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) | + macconf->ZeroQuantaPause | + macconf->PauseLowThreshold | + macconf->UnicastPauseFrameDetect | + macconf->ReceiveFlowControl | + macconf->TransmitFlowControl); + + /* Write to ETHERNET MACFCR */ + (heth->Instance)->MACFCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFCR = tmpreg1; + + /*----------------------- ETHERNET MACVLANTR Configuration -----------------*/ + (heth->Instance)->MACVLANTR = (uint32_t)(macconf->VLANTagComparison | + macconf->VLANTagIdentifier); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACVLANTR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACVLANTR = tmpreg1; + } + else /* macconf == NULL : here we just configure Speed and Duplex mode */ + { + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + + /* Clear FES and DM bits */ + tmpreg1 &= ~(0x00004800U); + + tmpreg1 |= (uint32_t)(heth->Init.Speed | heth->Init.DuplexMode); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + } + + /* Set the ETH state to Ready */ + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Sets ETH DMA Configuration. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf DMA Configuration structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef *dmaconf) +{ + uint32_t tmpreg1 = 0U; + + /* Process Locked */ + __HAL_LOCK(heth); + + /* Set the ETH peripheral state to BUSY */ + heth->State= HAL_ETH_STATE_BUSY; + + /* Check parameters */ + assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(dmaconf->DropTCPIPChecksumErrorFrame)); + assert_param(IS_ETH_RECEIVE_STORE_FORWARD(dmaconf->ReceiveStoreForward)); + assert_param(IS_ETH_FLUSH_RECEIVE_FRAME(dmaconf->FlushReceivedFrame)); + assert_param(IS_ETH_TRANSMIT_STORE_FORWARD(dmaconf->TransmitStoreForward)); + assert_param(IS_ETH_TRANSMIT_THRESHOLD_CONTROL(dmaconf->TransmitThresholdControl)); + assert_param(IS_ETH_FORWARD_ERROR_FRAMES(dmaconf->ForwardErrorFrames)); + assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(dmaconf->ForwardUndersizedGoodFrames)); + assert_param(IS_ETH_RECEIVE_THRESHOLD_CONTROL(dmaconf->ReceiveThresholdControl)); + assert_param(IS_ETH_SECOND_FRAME_OPERATE(dmaconf->SecondFrameOperate)); + assert_param(IS_ETH_ADDRESS_ALIGNED_BEATS(dmaconf->AddressAlignedBeats)); + assert_param(IS_ETH_FIXED_BURST(dmaconf->FixedBurst)); + assert_param(IS_ETH_RXDMA_BURST_LENGTH(dmaconf->RxDMABurstLength)); + assert_param(IS_ETH_TXDMA_BURST_LENGTH(dmaconf->TxDMABurstLength)); + assert_param(IS_ETH_ENHANCED_DESCRIPTOR_FORMAT(dmaconf->EnhancedDescriptorFormat)); + assert_param(IS_ETH_DMA_DESC_SKIP_LENGTH(dmaconf->DescriptorSkipLength)); + assert_param(IS_ETH_DMA_ARBITRATION_ROUNDROBIN_RXTX(dmaconf->DMAArbitration)); + + /*----------------------- ETHERNET DMAOMR Configuration --------------------*/ + /* Get the ETHERNET DMAOMR value */ + tmpreg1 = (heth->Instance)->DMAOMR; + /* Clear xx bits */ + tmpreg1 &= ETH_DMAOMR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(dmaconf->DropTCPIPChecksumErrorFrame | + dmaconf->ReceiveStoreForward | + dmaconf->FlushReceivedFrame | + dmaconf->TransmitStoreForward | + dmaconf->TransmitThresholdControl | + dmaconf->ForwardErrorFrames | + dmaconf->ForwardUndersizedGoodFrames | + dmaconf->ReceiveThresholdControl | + dmaconf->SecondFrameOperate); + + /* Write to ETHERNET DMAOMR */ + (heth->Instance)->DMAOMR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; + + /*----------------------- ETHERNET DMABMR Configuration --------------------*/ + (heth->Instance)->DMABMR = (uint32_t)(dmaconf->AddressAlignedBeats | + dmaconf->FixedBurst | + dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */ + dmaconf->TxDMABurstLength | + dmaconf->EnhancedDescriptorFormat | + (dmaconf->DescriptorSkipLength << 2U) | + dmaconf->DMAArbitration | + ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMABMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMABMR = tmpreg1; + + /* Set the ETH state to Ready */ + heth->State= HAL_ETH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(heth); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * + @verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + (+) Get the ETH handle state: + HAL_ETH_GetState(); + + + @endverbatim + * @{ + */ + +/** + * @brief Return the ETH HAL state + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth) +{ + /* Return ETH state */ + return heth->State; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions + * @{ + */ + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param err Ethernet Init error + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err) +{ + ETH_MACInitTypeDef macinit; + ETH_DMAInitTypeDef dmainit; + uint32_t tmpreg1 = 0U; + + if (err != ETH_SUCCESS) /* Auto-negotiation failed */ + { + /* Set Ethernet duplex mode to Full-duplex */ + (heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX; + + /* Set Ethernet speed to 100M */ + (heth->Init).Speed = ETH_SPEED_100M; + } + + /* Ethernet MAC default initialization **************************************/ + macinit.Watchdog = ETH_WATCHDOG_ENABLE; + macinit.Jabber = ETH_JABBER_ENABLE; + macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT; + macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE; + macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE; + macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE; + if(heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) + { + macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } + else + { + macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE; + macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE; + macinit.BackOffLimit = ETH_BACKOFFLIMIT_10; + macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE; + macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE; + macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE; + macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL; + macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE; + macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL; + macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE; + macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT; + macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT; + macinit.HashTableHigh = 0x0U; + macinit.HashTableLow = 0x0U; + macinit.PauseTime = 0x0U; + macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE; + macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE; + macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE; + macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE; + macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT; + macinit.VLANTagIdentifier = 0x0U; + + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpreg1 &= ETH_MACCR_CLEAR_MASK; + /* Set the WD bit according to ETH Watchdog value */ + /* Set the JD: bit according to ETH Jabber value */ + /* Set the IFG bit according to ETH InterFrameGap value */ + /* Set the DCRS bit according to ETH CarrierSense value */ + /* Set the FES bit according to ETH Speed value */ + /* Set the DO bit according to ETH ReceiveOwn value */ + /* Set the LM bit according to ETH LoopbackMode value */ + /* Set the DM bit according to ETH Mode value */ + /* Set the IPCO bit according to ETH ChecksumOffload value */ + /* Set the DR bit according to ETH RetryTransmission value */ + /* Set the ACS bit according to ETH AutomaticPadCRCStrip value */ + /* Set the BL bit according to ETH BackOffLimit value */ + /* Set the DC bit according to ETH DeferralCheck value */ + tmpreg1 |= (uint32_t)(macinit.Watchdog | + macinit.Jabber | + macinit.InterFrameGap | + macinit.CarrierSense | + (heth->Init).Speed | + macinit.ReceiveOwn | + macinit.LoopbackMode | + (heth->Init).DuplexMode | + macinit.ChecksumOffload | + macinit.RetryTransmission | + macinit.AutomaticPadCRCStrip | + macinit.BackOffLimit | + macinit.DeferralCheck); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /*----------------------- ETHERNET MACFFR Configuration --------------------*/ + /* Set the RA bit according to ETH ReceiveAll value */ + /* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */ + /* Set the PCF bit according to ETH PassControlFrames value */ + /* Set the DBF bit according to ETH BroadcastFramesReception value */ + /* Set the DAIF bit according to ETH DestinationAddrFilter value */ + /* Set the PR bit according to ETH PromiscuousMode value */ + /* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */ + /* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */ + /* Write to ETHERNET MACFFR */ + (heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll | + macinit.SourceAddrFilter | + macinit.PassControlFrames | + macinit.BroadcastFramesReception | + macinit.DestinationAddrFilter | + macinit.PromiscuousMode | + macinit.MulticastFramesFilter | + macinit.UnicastFramesFilter); + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFFR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFFR = tmpreg1; + + /*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/ + /* Write to ETHERNET MACHTHR */ + (heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh; + + /* Write to ETHERNET MACHTLR */ + (heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow; + /*----------------------- ETHERNET MACFCR Configuration -------------------*/ + + /* Get the ETHERNET MACFCR value */ + tmpreg1 = (heth->Instance)->MACFCR; + /* Clear xx bits */ + tmpreg1 &= ETH_MACFCR_CLEAR_MASK; + + /* Set the PT bit according to ETH PauseTime value */ + /* Set the DZPQ bit according to ETH ZeroQuantaPause value */ + /* Set the PLT bit according to ETH PauseLowThreshold value */ + /* Set the UP bit according to ETH UnicastPauseFrameDetect value */ + /* Set the RFE bit according to ETH ReceiveFlowControl value */ + /* Set the TFE bit according to ETH TransmitFlowControl value */ + tmpreg1 |= (uint32_t)((macinit.PauseTime << 16U) | + macinit.ZeroQuantaPause | + macinit.PauseLowThreshold | + macinit.UnicastPauseFrameDetect | + macinit.ReceiveFlowControl | + macinit.TransmitFlowControl); + + /* Write to ETHERNET MACFCR */ + (heth->Instance)->MACFCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFCR = tmpreg1; + + /*----------------------- ETHERNET MACVLANTR Configuration ----------------*/ + /* Set the ETV bit according to ETH VLANTagComparison value */ + /* Set the VL bit according to ETH VLANTagIdentifier value */ + (heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison | + macinit.VLANTagIdentifier); + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACVLANTR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACVLANTR = tmpreg1; + + /* Ethernet DMA default initialization ************************************/ + dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE; + dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE; + dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE; + dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE; + dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE; + dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE; + dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE; + dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE; + dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE; + dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmainit.EnhancedDescriptorFormat = ETH_DMAENHANCEDDESCRIPTOR_ENABLE; + dmainit.DescriptorSkipLength = 0x0U; + dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; + + /* Get the ETHERNET DMAOMR value */ + tmpreg1 = (heth->Instance)->DMAOMR; + /* Clear xx bits */ + tmpreg1 &= ETH_DMAOMR_CLEAR_MASK; + + /* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */ + /* Set the RSF bit according to ETH ReceiveStoreForward value */ + /* Set the DFF bit according to ETH FlushReceivedFrame value */ + /* Set the TSF bit according to ETH TransmitStoreForward value */ + /* Set the TTC bit according to ETH TransmitThresholdControl value */ + /* Set the FEF bit according to ETH ForwardErrorFrames value */ + /* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */ + /* Set the RTC bit according to ETH ReceiveThresholdControl value */ + /* Set the OSF bit according to ETH SecondFrameOperate value */ + tmpreg1 |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame | + dmainit.ReceiveStoreForward | + dmainit.FlushReceivedFrame | + dmainit.TransmitStoreForward | + dmainit.TransmitThresholdControl | + dmainit.ForwardErrorFrames | + dmainit.ForwardUndersizedGoodFrames | + dmainit.ReceiveThresholdControl | + dmainit.SecondFrameOperate); + + /* Write to ETHERNET DMAOMR */ + (heth->Instance)->DMAOMR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; + + /*----------------------- ETHERNET DMABMR Configuration ------------------*/ + /* Set the AAL bit according to ETH AddressAlignedBeats value */ + /* Set the FB bit according to ETH FixedBurst value */ + /* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */ + /* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */ + /* Set the Enhanced DMA descriptors bit according to ETH EnhancedDescriptorFormat value*/ + /* Set the DSL bit according to ETH DesciptorSkipLength value */ + /* Set the PR and DA bits according to ETH DMAArbitration value */ + (heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats | + dmainit.FixedBurst | + dmainit.RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */ + dmainit.TxDMABurstLength | + dmainit.EnhancedDescriptorFormat | + (dmainit.DescriptorSkipLength << 2U) | + dmainit.DMAArbitration | + ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMABMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMABMR = tmpreg1; + + if((heth->Init).RxMode == ETH_RXINTERRUPT_MODE) + { + /* Enable the Ethernet Rx Interrupt */ + __HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R); + } + + /* Initialize MAC address in ethernet MAC */ + ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr); +} + +/** + * @brief Configures the selected MAC address. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param MacAddr The MAC address to configure + * This parameter can be one of the following values: + * @arg ETH_MAC_Address0: MAC Address0 + * @arg ETH_MAC_Address1: MAC Address1 + * @arg ETH_MAC_Address2: MAC Address2 + * @arg ETH_MAC_Address3: MAC Address3 + * @param Addr Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg1; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + + /* Check the parameters */ + assert_param(IS_ETH_MAC_ADDRESS0123(MacAddr)); + + /* Calculate the selected MAC address high register */ + tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U]; + /* Load the selected MAC address high register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1; + /* Calculate the selected MAC address low register */ + tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U]; + + /* Load the selected MAC address low register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1; +} + +/** + * @brief Enables the MAC transmission. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg1 = 0U; + + /* Enable the MAC transmission */ + (heth->Instance)->MACCR |= ETH_MACCR_TE; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + ETH_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; +} + +/** + * @brief Disables the MAC transmission. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg1 = 0U; + + /* Disable the MAC transmission */ + (heth->Instance)->MACCR &= ~ETH_MACCR_TE; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + ETH_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; +} + +/** + * @brief Enables the MAC reception. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg1 = 0U; + + /* Enable the MAC reception */ + (heth->Instance)->MACCR |= ETH_MACCR_RE; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + ETH_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; +} + +/** + * @brief Disables the MAC reception. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg1 = 0U; + + /* Disable the MAC reception */ + (heth->Instance)->MACCR &= ~ETH_MACCR_RE; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + ETH_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; +} + +/** + * @brief Enables the DMA transmission. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth) +{ + /* Enable the DMA transmission */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_ST; +} + +/** + * @brief Disables the DMA transmission. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth) +{ + /* Disable the DMA transmission */ + (heth->Instance)->DMAOMR &= ~ETH_DMAOMR_ST; +} + +/** + * @brief Enables the DMA reception. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth) +{ + /* Enable the DMA reception */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_SR; +} + +/** + * @brief Disables the DMA reception. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth) +{ + /* Disable the DMA reception */ + (heth->Instance)->DMAOMR &= ~ETH_DMAOMR_SR; +} + +/** + * @brief Clears the ETHERNET transmit FIFO. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg1 = 0U; + + /* Set the Flush Transmit FIFO bit */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + ETH_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; +} + +/** + * @brief This function provides delay (in milliseconds) based on CPU cycles method. + * @param mdelay specifies the delay time length, in milliseconds. + * @retval None + */ +static void ETH_Delay(uint32_t mdelay) +{ + __IO uint32_t Delay = mdelay * (SystemCoreClock / 8U / 1000U); + do + { + __NOP(); + } + while (Delay --); +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->DMAErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak DMAErrorCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx ||\ + STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ +#endif /* HAL_ETH_LEGACY_MODULE_ENABLED*/ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/Makefile b/libs/STM32F4xx_HAL_Driver/Src/Makefile new file mode 100644 index 0000000..94fd109 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/Makefile @@ -0,0 +1,28 @@ +include ../../../Makefile.conf + +TARGET=libhal.a + +# Includes +CFLAGS+= -I../Inc +CFLAGS+= -I../../cmsis +CFLAGS+= -I../../../src + +C_FILES=$(wildcard *.c) +C_SRC=$(filter-out %template.c,$(C_FILES)) +C_OBJ=$(subst .c,.o,$(C_SRC)) + +OBJ=$(C_OBJ) + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(AR) -cr $@ $^ + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $^ + +clean: + rm -vf $(OBJ) + rm -vf $(TARGET) diff --git a/libs/hal/stm32f4xx_hal.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c similarity index 100% rename from libs/hal/stm32f4xx_hal.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c new file mode 100644 index 0000000..9ad943d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc.c @@ -0,0 +1,2110 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_adc.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the Analog to Digital Converter (ADC) peripheral: + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + Peripheral State functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 + ============================================================================== + ##### ADC Peripheral features ##### + ============================================================================== + [..] + (#) 12-bit, 10-bit, 8-bit or 6-bit configurable resolution. + (#) Interrupt generation at the end of conversion, end of injected conversion, + and in case of analog watchdog or overrun events + (#) Single and continuous conversion modes. + (#) Scan mode for automatic conversion of channel 0 to channel x. + (#) Data alignment with in-built data coherency. + (#) Channel-wise programmable sampling time. + (#) External trigger option with configurable polarity for both regular and + injected conversion. + (#) Dual/Triple mode (on devices with 2 ADCs or more). + (#) Configurable DMA data storage in Dual/Triple ADC mode. + (#) Configurable delay between conversions in Dual/Triple interleaved mode. + (#) ADC conversion type (refer to the datasheets). + (#) ADC supply requirements: 2.4 V to 3.6 V at full speed and down to 1.8 V at + slower speed. + (#) ADC input range: VREF(minus) = VIN = VREF(plus). + (#) DMA request generation during regular channel conversion. + + + ##### How to use this driver ##### + ============================================================================== + [..] + (#)Initialize the ADC low level resources by implementing the HAL_ADC_MspInit(): + (##) Enable the ADC interface clock using __HAL_RCC_ADC_CLK_ENABLE() + (##) ADC pins configuration + (+++) Enable the clock for the ADC GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE() + (+++) Configure these ADC pins in analog mode using HAL_GPIO_Init() + (##) In case of using interrupts (e.g. HAL_ADC_Start_IT()) + (+++) Configure the ADC interrupt priority using HAL_NVIC_SetPriority() + (+++) Enable the ADC IRQ handler using HAL_NVIC_EnableIRQ() + (+++) In ADC IRQ handler, call HAL_ADC_IRQHandler() + (##) In case of using DMA to control data transfer (e.g. HAL_ADC_Start_DMA()) + (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE() + (+++) Configure and enable two DMA streams stream for managing data + transfer from peripheral to memory (output stream) + (+++) Associate the initialized DMA handle to the CRYP DMA handle + using __HAL_LINKDMA() + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the two DMA Streams. The output stream should have higher + priority than the input stream. + + *** Configuration of ADC, groups regular/injected, channels parameters *** + ============================================================================== + [..] + (#) Configure the ADC parameters (resolution, data alignment, ...) + and regular group parameters (conversion trigger, sequencer, ...) + using function HAL_ADC_Init(). + + (#) Configure the channels for regular group parameters (channel number, + channel rank into sequencer, ..., into regular group) + using function HAL_ADC_ConfigChannel(). + + (#) Optionally, configure the injected group parameters (conversion trigger, + sequencer, ..., of injected group) + and the channels for injected group parameters (channel number, + channel rank into sequencer, ..., into injected group) + using function HAL_ADCEx_InjectedConfigChannel(). + + (#) Optionally, configure the analog watchdog parameters (channels + monitored, thresholds, ...) using function HAL_ADC_AnalogWDGConfig(). + + (#) Optionally, for devices with several ADC instances: configure the + multimode parameters using function HAL_ADCEx_MultiModeConfigChannel(). + + *** Execution of ADC conversions *** + ============================================================================== + [..] + (#) ADC driver can be used among three modes: polling, interruption, + transfer by DMA. + + *** Polling mode IO operation *** + ================================= + [..] + (+) Start the ADC peripheral using HAL_ADC_Start() + (+) Wait for end of conversion using HAL_ADC_PollForConversion(), at this stage + user can specify the value of timeout according to his end application + (+) To read the ADC converted values, use the HAL_ADC_GetValue() function. + (+) Stop the ADC peripheral using HAL_ADC_Stop() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Start the ADC peripheral using HAL_ADC_Start_IT() + (+) Use HAL_ADC_IRQHandler() called under ADC_IRQHandler() Interrupt subroutine + (+) At ADC end of conversion HAL_ADC_ConvCpltCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADC_ConvCpltCallback + (+) In case of ADC Error, HAL_ADC_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADC_ErrorCallback + (+) Stop the ADC peripheral using HAL_ADC_Stop_IT() + + *** DMA mode IO operation *** + ============================== + [..] + (+) Start the ADC peripheral using HAL_ADC_Start_DMA(), at this stage the user specify the length + of data to be transferred at each end of conversion + (+) At The end of data transfer by HAL_ADC_ConvCpltCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADC_ConvCpltCallback + (+) In case of transfer Error, HAL_ADC_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADC_ErrorCallback + (+) Stop the ADC peripheral using HAL_ADC_Stop_DMA() + + *** ADC HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in ADC HAL driver. + + (+) __HAL_ADC_ENABLE : Enable the ADC peripheral + (+) __HAL_ADC_DISABLE : Disable the ADC peripheral + (+) __HAL_ADC_ENABLE_IT: Enable the ADC end of conversion interrupt + (+) __HAL_ADC_DISABLE_IT: Disable the ADC end of conversion interrupt + (+) __HAL_ADC_GET_IT_SOURCE: Check if the specified ADC interrupt source is enabled or disabled + (+) __HAL_ADC_CLEAR_FLAG: Clear the ADC's pending flags + (+) __HAL_ADC_GET_FLAG: Get the selected ADC's flag status + (+) ADC_GET_RESOLUTION: Return resolution bits in CR1 register + + [..] + (@) You can refer to the ADC HAL driver header file for more useful macros + + *** Deinitialization of ADC *** + ============================================================================== + [..] + (#) Disable the ADC interface + (++) ADC clock can be hard reset and disabled at RCC top level. + (++) Hard reset of ADC peripherals + using macro __HAL_RCC_ADC_FORCE_RESET(), __HAL_RCC_ADC_RELEASE_RESET(). + (++) ADC clock disable using the equivalent macro/functions as configuration step. + (+++) Example: + Into HAL_ADC_MspDeInit() (recommended code location) or with + other device clock parameters configuration: + (+++) HAL_RCC_GetOscConfig(&RCC_OscInitStructure); + (+++) RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI; + (+++) RCC_OscInitStructure.HSIState = RCC_HSI_OFF; (if not used for system clock) + (+++) HAL_RCC_OscConfig(&RCC_OscInitStructure); + + (#) ADC pins configuration + (++) Disable the clock for the ADC GPIOs using macro __HAL_RCC_GPIOx_CLK_DISABLE() + + (#) Optionally, in case of usage of ADC with interruptions: + (++) Disable the NVIC for ADC using function HAL_NVIC_DisableIRQ(ADCx_IRQn) + + (#) Optionally, in case of usage of DMA: + (++) Deinitialize the DMA using function HAL_DMA_DeInit(). + (++) Disable the NVIC for DMA using function HAL_NVIC_DisableIRQ(DMAx_Channelx_IRQn) + *** Callback registration *** + ============================================================================== + [..] + + The compilation flag USE_HAL_ADC_REGISTER_CALLBACKS, when set to 1, + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_ADC_RegisterCallback() + to register an interrupt callback. + [..] + + Function HAL_ADC_RegisterCallback() allows to register following callbacks: + (+) ConvCpltCallback : ADC conversion complete callback + (+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback + (+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback + (+) ErrorCallback : ADC error callback + (+) InjectedConvCpltCallback : ADC group injected conversion complete callback + (+) InjectedQueueOverflowCallback : ADC group injected context queue overflow callback + (+) LevelOutOfWindow2Callback : ADC analog watchdog 2 callback + (+) LevelOutOfWindow3Callback : ADC analog watchdog 3 callback + (+) EndOfSamplingCallback : ADC end of sampling callback + (+) MspInitCallback : ADC Msp Init callback + (+) MspDeInitCallback : ADC Msp DeInit callback + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + + Use function HAL_ADC_UnRegisterCallback to reset a callback to the default + weak function. + [..] + + HAL_ADC_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) ConvCpltCallback : ADC conversion complete callback + (+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback + (+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback + (+) ErrorCallback : ADC error callback + (+) InjectedConvCpltCallback : ADC group injected conversion complete callback + (+) InjectedQueueOverflowCallback : ADC group injected context queue overflow callback + (+) LevelOutOfWindow2Callback : ADC analog watchdog 2 callback + (+) LevelOutOfWindow3Callback : ADC analog watchdog 3 callback + (+) EndOfSamplingCallback : ADC end of sampling callback + (+) MspInitCallback : ADC Msp Init callback + (+) MspDeInitCallback : ADC Msp DeInit callback + [..] + + By default, after the HAL_ADC_Init() and when the state is HAL_ADC_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ADC_ConvCpltCallback(), HAL_ADC_ErrorCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_ADC_Init()/ HAL_ADC_DeInit() only when + these callbacks are null (not registered beforehand). + [..] + + If MspInit or MspDeInit are not null, the HAL_ADC_Init()/ HAL_ADC_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + [..] + + Callbacks can be registered/unregistered in HAL_ADC_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_ADC_STATE_READY or HAL_ADC_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + [..] + + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_ADC_RegisterCallback() before calling HAL_ADC_DeInit() + or HAL_ADC_Init() function. + [..] + + When the compilation flag USE_HAL_ADC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup ADC ADC + * @brief ADC driver modules + * @{ + */ + +#ifdef HAL_ADC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @addtogroup ADC_Private_Functions + * @{ + */ +/* Private function prototypes -----------------------------------------------*/ +static void ADC_Init(ADC_HandleTypeDef *hadc); +static void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma); +static void ADC_DMAError(DMA_HandleTypeDef *hdma); +static void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma); +/** + * @} + */ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup ADC_Exported_Functions ADC Exported Functions + * @{ + */ + +/** @defgroup ADC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the ADC. + (+) De-initialize the ADC. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct and initializes the ADC MSP. + * + * @note This function is used to configure the global features of the ADC ( + * ClockPrescaler, Resolution, Data Alignment and number of conversion), however, + * the rest of the configuration parameters are specific to the regular + * channels group (scan mode activation, continuous mode activation, + * External trigger source and edge, DMA continuous request after the + * last transfer and End of conversion selection). + * + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + + /* Check ADC handle */ + if (hadc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + assert_param(IS_ADC_CLOCKPRESCALER(hadc->Init.ClockPrescaler)); + assert_param(IS_ADC_RESOLUTION(hadc->Init.Resolution)); + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ScanConvMode)); + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG(hadc->Init.ExternalTrigConv)); + assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign)); + assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion)); + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests)); + assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection)); + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode)); + + if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START) + { + assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); + } + + if (hadc->State == HAL_ADC_STATE_RESET) + { +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + /* Init the ADC Callback settings */ + hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback; /* Legacy weak callback */ + hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback; /* Legacy weak callback */ + hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback; /* Legacy weak callback */ + hadc->ErrorCallback = HAL_ADC_ErrorCallback; /* Legacy weak callback */ + hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback; /* Legacy weak callback */ + if (hadc->MspInitCallback == NULL) + { + hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware */ + hadc->MspInitCallback(hadc); +#else + /* Init the low level hardware */ + HAL_ADC_MspInit(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Initialize ADC error code */ + ADC_CLEAR_ERRORCODE(hadc); + + /* Allocate lock resource and initialize it */ + hadc->Lock = HAL_UNLOCKED; + } + + /* Configuration of ADC parameters if previous preliminary actions are */ + /* correctly completed. */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL)) + { + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_BUSY_INTERNAL); + + /* Set ADC parameters */ + ADC_Init(hadc); + + /* Set ADC error code to none */ + ADC_CLEAR_ERRORCODE(hadc); + + /* Set the ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_BUSY_INTERNAL, + HAL_ADC_STATE_READY); + } + else + { + tmp_hal_status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +/** + * @brief Deinitializes the ADCx peripheral registers to their default reset values. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + + /* Check ADC handle */ + if (hadc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL); + + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Configuration of ADC parameters if previous preliminary actions are */ + /* correctly completed. */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + if (hadc->MspDeInitCallback == NULL) + { + hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: RCC clock, NVIC */ + hadc->MspDeInitCallback(hadc); +#else + /* DeInit the low level hardware: RCC clock, NVIC */ + HAL_ADC_MspDeInit(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Set ADC error code to none */ + ADC_CLEAR_ERRORCODE(hadc); + + /* Set ADC state */ + hadc->State = HAL_ADC_STATE_RESET; + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ADC Callback + * To be used instead of the weak predefined callback + * @param hadc Pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID + * @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion DMA half-transfer callback ID + * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID + * @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID + * @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID + * @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID + * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + if ((hadc->State & HAL_ADC_STATE_READY) != 0UL) + { + switch (CallbackID) + { + case HAL_ADC_CONVERSION_COMPLETE_CB_ID : + hadc->ConvCpltCallback = pCallback; + break; + + case HAL_ADC_CONVERSION_HALF_CB_ID : + hadc->ConvHalfCpltCallback = pCallback; + break; + + case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID : + hadc->LevelOutOfWindowCallback = pCallback; + break; + + case HAL_ADC_ERROR_CB_ID : + hadc->ErrorCallback = pCallback; + break; + + case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID : + hadc->InjectedConvCpltCallback = pCallback; + break; + + case HAL_ADC_MSPINIT_CB_ID : + hadc->MspInitCallback = pCallback; + break; + + case HAL_ADC_MSPDEINIT_CB_ID : + hadc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_ADC_STATE_RESET == hadc->State) + { + switch (CallbackID) + { + case HAL_ADC_MSPINIT_CB_ID : + hadc->MspInitCallback = pCallback; + break; + + case HAL_ADC_MSPDEINIT_CB_ID : + hadc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister a ADC Callback + * ADC callback is redirected to the weak predefined callback + * @param hadc Pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID + * @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion DMA half-transfer callback ID + * @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID + * @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID + * @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID + * @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID + * @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if ((hadc->State & HAL_ADC_STATE_READY) != 0UL) + { + switch (CallbackID) + { + case HAL_ADC_CONVERSION_COMPLETE_CB_ID : + hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback; + break; + + case HAL_ADC_CONVERSION_HALF_CB_ID : + hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback; + break; + + case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID : + hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback; + break; + + case HAL_ADC_ERROR_CB_ID : + hadc->ErrorCallback = HAL_ADC_ErrorCallback; + break; + + case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID : + hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback; + break; + + case HAL_ADC_MSPINIT_CB_ID : + hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_ADC_MSPDEINIT_CB_ID : + hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_ADC_STATE_RESET == hadc->State) + { + switch (CallbackID) + { + case HAL_ADC_MSPINIT_CB_ID : + hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_ADC_MSPDEINIT_CB_ID : + hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + +/** + * @brief Initializes the ADC MSP. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes the ADC MSP. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup ADC_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Start conversion of regular channel. + (+) Stop conversion of regular channel. + (+) Start conversion of regular channel and enable interrupt. + (+) Stop conversion of regular channel and disable interrupt. + (+) Start conversion of regular channel and enable DMA transfer. + (+) Stop conversion of regular channel and disable DMA transfer. + (+) Handle ADC interrupt request. + +@endverbatim + * @{ + */ + +/** + * @brief Enables ADC and starts conversion of the regular channels. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc) +{ + __IO uint32_t counter = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Enable the ADC peripheral */ + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for ADC stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to regular group conversion results */ + /* - Set state bitfield related to regular group operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR, + HAL_ADC_STATE_REG_BUSY); + + /* If conversions on group regular are also triggering group injected, */ + /* update ADC state. */ + if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET) + { + ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); + } + + /* State machine update: Check if an injected conversion is ongoing */ + if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + /* Reset ADC error code fields related to conversions on group regular */ + CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA)); + } + else + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Clear regular group conversion flag and overrun flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC | ADC_FLAG_OVR); + + /* Check if Multimode enabled */ + if (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_MULTI)) + { +#if defined(ADC2) && defined(ADC3) + if ((hadc->Instance == ADC1) || ((hadc->Instance == ADC2) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_0)) \ + || ((hadc->Instance == ADC3) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_4))) + { +#endif /* ADC2 || ADC3 */ + /* if no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } +#if defined(ADC2) && defined(ADC3) + } +#endif /* ADC2 || ADC3 */ + } + else + { + /* if instance of handle correspond to ADC1 and no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance == ADC1) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Disables ADC and stop conversion of regular channels. + * + * @note Caution: This function will stop also injected channels. + * + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Poll for regular conversion complete + * @note ADC conversion flags EOS (end of sequence) and EOC (end of + * conversion) are cleared by this function. + * @note This function cannot be used in a particular setup: ADC configured + * in DMA mode and polling for end of each conversion (ADC init + * parameter "EOCSelection" set to ADC_EOC_SINGLE_CONV). + * In this case, DMA resets the flag EOC and polling cannot be + * performed on each conversion. Nevertheless, polling can still + * be performed on the complete sequence. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param Timeout Timeout value in millisecond. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Verification that ADC configuration is compliant with polling for */ + /* each conversion: */ + /* Particular case is ADC configured in DMA mode and ADC sequencer with */ + /* several ranks and polling for end of each conversion. */ + /* For code simplicity sake, this particular case is generalized to */ + /* ADC configured in DMA mode and polling for end of each conversion. */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_EOCS) && + HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_DMA)) + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + return HAL_ERROR; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check End of conversion flag */ + while (!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))) + { + /* Check if timeout is disabled (set to infinite wait) */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* New check to avoid false timeout detection in case of preemption */ + if (!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))) + { + /* Update ADC state machine to timeout */ + SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT); + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + return HAL_TIMEOUT; + } + } + } + } + + /* Clear regular group conversion flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC); + + /* Update ADC state machine */ + SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC); + + /* Determine whether any further conversion upcoming on group regular */ + /* by external trigger, continuous mode or scan sequence on going. */ + /* Note: On STM32F4, there is no independent flag of end of sequence. */ + /* The test of scan sequence on going is done either with scan */ + /* sequence disabled or with end of conversion flag set to */ + /* of end of sequence. */ + if (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE) && + (HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS))) + { + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Return ADC state */ + return HAL_OK; +} + +/** + * @brief Poll for conversion event + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param EventType the ADC event type. + * This parameter can be one of the following values: + * @arg ADC_AWD_EVENT: ADC Analog watch Dog event. + * @arg ADC_OVR_EVENT: ADC Overrun event. + * @param Timeout Timeout value in millisecond. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef *hadc, uint32_t EventType, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + assert_param(IS_ADC_EVENT_TYPE(EventType)); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check selected event flag */ + while (!(__HAL_ADC_GET_FLAG(hadc, EventType))) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* New check to avoid false timeout detection in case of preemption */ + if (!(__HAL_ADC_GET_FLAG(hadc, EventType))) + { + /* Update ADC state machine to timeout */ + SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT); + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + return HAL_TIMEOUT; + } + } + } + } + + /* Analog watchdog (level out of window) event */ + if (EventType == ADC_AWD_EVENT) + { + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_AWD1); + + /* Clear ADC analog watchdog flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD); + } + /* Overrun event */ + else + { + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_REG_OVR); + /* Set ADC error code to overrun */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR); + + /* Clear ADC overrun flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR); + } + + /* Return ADC state */ + return HAL_OK; +} + + +/** + * @brief Enables the interrupt and starts ADC conversion of regular channels. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc) +{ + __IO uint32_t counter = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Enable the ADC peripheral */ + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for ADC stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to regular group conversion results */ + /* - Set state bitfield related to regular group operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR, + HAL_ADC_STATE_REG_BUSY); + + /* If conversions on group regular are also triggering group injected, */ + /* update ADC state. */ + if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET) + { + ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); + } + + /* State machine update: Check if an injected conversion is ongoing */ + if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + /* Reset ADC error code fields related to conversions on group regular */ + CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA)); + } + else + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Clear regular group conversion flag and overrun flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC | ADC_FLAG_OVR); + + /* Enable end of conversion interrupt for regular group */ + __HAL_ADC_ENABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_OVR)); + + /* Check if Multimode enabled */ + if (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_MULTI)) + { +#if defined(ADC2) && defined(ADC3) + if ((hadc->Instance == ADC1) || ((hadc->Instance == ADC2) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_0)) \ + || ((hadc->Instance == ADC3) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_4))) + { +#endif /* ADC2 || ADC3 */ + /* if no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } +#if defined(ADC2) && defined(ADC3) + } +#endif /* ADC2 || ADC3 */ + } + else + { + /* if instance of handle correspond to ADC1 and no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance == ADC1) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Disables the interrupt and stop ADC conversion of regular channels. + * + * @note Caution: This function will stop also injected channels. + * + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc) +{ + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Disable ADC end of conversion interrupt for regular group */ + __HAL_ADC_DISABLE_IT(hadc, (ADC_IT_EOC | ADC_IT_OVR)); + + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Handles ADC interrupt request + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +void HAL_ADC_IRQHandler(ADC_HandleTypeDef *hadc) +{ + uint32_t tmp1 = 0U, tmp2 = 0U; + + uint32_t tmp_sr = hadc->Instance->SR; + uint32_t tmp_cr1 = hadc->Instance->CR1; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_REGULAR_LENGTH(hadc->Init.NbrOfConversion)); + assert_param(IS_ADC_EOCSelection(hadc->Init.EOCSelection)); + + tmp1 = tmp_sr & ADC_FLAG_EOC; + tmp2 = tmp_cr1 & ADC_IT_EOC; + /* Check End of conversion flag for regular channels */ + if (tmp1 && tmp2) + { + /* Update state machine on conversion status if not in error state */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL)) + { + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC); + } + + /* Determine whether any further conversion upcoming on group regular */ + /* by external trigger, continuous mode or scan sequence on going. */ + /* Note: On STM32F4, there is no independent flag of end of sequence. */ + /* The test of scan sequence on going is done either with scan */ + /* sequence disabled or with end of conversion flag set to */ + /* of end of sequence. */ + if (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE) && + (HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS))) + { + /* Disable ADC end of single conversion interrupt on group regular */ + /* Note: Overrun interrupt was enabled with EOC interrupt in */ + /* HAL_ADC_Start_IT(), but is not disabled here because can be used */ + /* by overrun IRQ process below. */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC); + + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Conversion complete callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ConvCpltCallback(hadc); +#else + HAL_ADC_ConvCpltCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Clear regular group conversion flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC); + } + + tmp1 = tmp_sr & ADC_FLAG_JEOC; + tmp2 = tmp_cr1 & ADC_IT_JEOC; + /* Check End of conversion flag for injected channels */ + if (tmp1 && tmp2) + { + /* Update state machine on conversion status if not in error state */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL)) + { + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC); + } + + /* Determine whether any further conversion upcoming on group injected */ + /* by external trigger, scan sequence on going or by automatic injected */ + /* conversion from group regular (same conditions as group regular */ + /* interruption disabling above). */ + if (ADC_IS_SOFTWARE_START_INJECTED(hadc) && + (HAL_IS_BIT_CLR(hadc->Instance->JSQR, ADC_JSQR_JL) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS)) && + (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) && + (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE)))) + { + /* Disable ADC end of single conversion interrupt on group injected */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC); + + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Conversion complete callback */ + /* Conversion complete callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->InjectedConvCpltCallback(hadc); +#else + HAL_ADCEx_InjectedConvCpltCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Clear injected group conversion flag */ + __HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JSTRT | ADC_FLAG_JEOC)); + } + + tmp1 = tmp_sr & ADC_FLAG_AWD; + tmp2 = tmp_cr1 & ADC_IT_AWD; + /* Check Analog watchdog flag */ + if (tmp1 && tmp2) + { + if (__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_AWD)) + { + /* Set ADC state */ + SET_BIT(hadc->State, HAL_ADC_STATE_AWD1); + + /* Level out of window callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->LevelOutOfWindowCallback(hadc); +#else + HAL_ADC_LevelOutOfWindowCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Clear the ADC analog watchdog flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD); + } + } + + tmp1 = tmp_sr & ADC_FLAG_OVR; + tmp2 = tmp_cr1 & ADC_IT_OVR; + /* Check Overrun flag */ + if (tmp1 && tmp2) + { + /* Note: On STM32F4, ADC overrun can be set through other parameters */ + /* refer to description of parameter "EOCSelection" for more */ + /* details. */ + + /* Set ADC error code to overrun */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_OVR); + + /* Clear ADC overrun flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR); + + /* Error callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ErrorCallback(hadc); +#else + HAL_ADC_ErrorCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + + /* Clear the Overrun flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_OVR); + } +} + +/** + * @brief Enables ADC DMA request after last transfer (Single-ADC mode) and enables ADC peripheral + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param pData The destination Buffer address. + * @param Length The length of data to be transferred from ADC peripheral to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length) +{ + __IO uint32_t counter = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Enable the ADC peripheral */ + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for ADC stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Check ADC DMA Mode */ + /* - disable the DMA Mode if it is already enabled */ + if ((hadc->Instance->CR2 & ADC_CR2_DMA) == ADC_CR2_DMA) + { + CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA); + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to regular group conversion results */ + /* - Set state bitfield related to regular group operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR, + HAL_ADC_STATE_REG_BUSY); + + /* If conversions on group regular are also triggering group injected, */ + /* update ADC state. */ + if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET) + { + ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); + } + + /* State machine update: Check if an injected conversion is ongoing */ + if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + /* Reset ADC error code fields related to conversions on group regular */ + CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA)); + } + else + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Set the DMA transfer complete callback */ + hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt; + + /* Set the DMA half transfer complete callback */ + hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt; + + /* Set the DMA error callback */ + hadc->DMA_Handle->XferErrorCallback = ADC_DMAError; + + + /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */ + /* start (in case of SW start): */ + + /* Clear regular group conversion flag and overrun flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC | ADC_FLAG_OVR); + + /* Enable ADC overrun interrupt */ + __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR); + + /* Enable ADC DMA mode */ + hadc->Instance->CR2 |= ADC_CR2_DMA; + + /* Start the DMA channel */ + HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length); + + /* Check if Multimode enabled */ + if (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_MULTI)) + { +#if defined(ADC2) && defined(ADC3) + if ((hadc->Instance == ADC1) || ((hadc->Instance == ADC2) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_0)) \ + || ((hadc->Instance == ADC3) && ((ADC->CCR & ADC_CCR_MULTI_Msk) < ADC_CCR_MULTI_4))) + { +#endif /* ADC2 || ADC3 */ + /* if no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } +#if defined(ADC2) && defined(ADC3) + } +#endif /* ADC2 || ADC3 */ + } + else + { + /* if instance of handle correspond to ADC1 and no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance == ADC1) && ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET)) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Disables ADC DMA (Single-ADC mode) and disables ADC peripheral + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Disable the selected ADC DMA mode */ + hadc->Instance->CR2 &= ~ADC_CR2_DMA; + + /* Disable the DMA channel (in case of DMA in circular mode or stop while */ + /* DMA transfer is on going) */ + if (hadc->DMA_Handle->State == HAL_DMA_STATE_BUSY) + { + tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle); + + /* Check if DMA channel effectively disabled */ + if (tmp_hal_status != HAL_OK) + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA); + } + } + + /* Disable ADC overrun interrupt */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR); + + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +/** + * @brief Gets the converted value from data register of regular channel. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval Converted value + */ +uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc) +{ + /* Return the selected ADC converted value */ + return hadc->Instance->DR; +} + +/** + * @brief Regular conversion complete callback in non blocking mode + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_ConvCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Regular conversion half DMA transfer callback in non blocking mode + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_ConvHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Analog watchdog callback in non blocking mode + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_LevelOoutOfWindowCallback could be implemented in the user file + */ +} + +/** + * @brief Error ADC callback. + * @note In case of error due to overrun when using ADC with DMA transfer + * (HAL ADC handle parameter "ErrorCode" to state "HAL_ADC_ERROR_OVR"): + * - Reinitialize the DMA using function "HAL_ADC_Stop_DMA()". + * - If needed, restart a new ADC conversion using function + * "HAL_ADC_Start_DMA()" + * (this function is also clearing overrun flag) + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup ADC_Exported_Functions_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure regular channels. + (+) Configure injected channels. + (+) Configure multimode. + (+) Configure the analog watch dog. + +@endverbatim + * @{ + */ + +/** +* @brief Configures for the selected ADC regular channel its corresponding +* rank in the sequencer and its sample time. +* @param hadc pointer to a ADC_HandleTypeDef structure that contains +* the configuration information for the specified ADC. +* @param sConfig ADC configuration structure. +* @retval HAL status +*/ +HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, ADC_ChannelConfTypeDef *sConfig) +{ + __IO uint32_t counter = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_ADC_CHANNEL(sConfig->Channel)); + assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank)); + assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (sConfig->Channel > ADC_CHANNEL_9) + { + /* Clear the old sample time */ + hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel); + + /* Set the new sample time */ + hadc->Instance->SMPR1 |= ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel); + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Clear the old sample time */ + hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel); + + /* Set the new sample time */ + hadc->Instance->SMPR2 |= ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel); + } + + /* For Rank 1 to 6 */ + if (sConfig->Rank < 7U) + { + /* Clear the old SQx bits for the selected rank */ + hadc->Instance->SQR3 &= ~ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank); + + /* Set the SQx bits for the selected rank */ + hadc->Instance->SQR3 |= ADC_SQR3_RK(sConfig->Channel, sConfig->Rank); + } + /* For Rank 7 to 12 */ + else if (sConfig->Rank < 13U) + { + /* Clear the old SQx bits for the selected rank */ + hadc->Instance->SQR2 &= ~ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank); + + /* Set the SQx bits for the selected rank */ + hadc->Instance->SQR2 |= ADC_SQR2_RK(sConfig->Channel, sConfig->Rank); + } + /* For Rank 13 to 16 */ + else + { + /* Clear the old SQx bits for the selected rank */ + hadc->Instance->SQR1 &= ~ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank); + + /* Set the SQx bits for the selected rank */ + hadc->Instance->SQR1 |= ADC_SQR1_RK(sConfig->Channel, sConfig->Rank); + } + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* if ADC1 Channel_18 is selected for VBAT Channel ennable VBATE */ + if ((hadc->Instance == ADC1) && (sConfig->Channel == ADC_CHANNEL_VBAT)) + { + /* Disable the TEMPSENSOR channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/ + if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT) + { + tmpADC_Common->CCR &= ~ADC_CCR_TSVREFE; + } + /* Enable the VBAT channel*/ + tmpADC_Common->CCR |= ADC_CCR_VBATE; + } + + /* if ADC1 Channel_16 or Channel_18 is selected for Temperature sensor or + Channel_17 is selected for VREFINT enable TSVREFE */ + if ((hadc->Instance == ADC1) && ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) || (sConfig->Channel == ADC_CHANNEL_VREFINT))) + { + /* Disable the VBAT channel in case of using board with multiplixed ADC_CHANNEL_VBAT & ADC_CHANNEL_TEMPSENSOR*/ + if ((uint16_t)ADC_CHANNEL_TEMPSENSOR == (uint16_t)ADC_CHANNEL_VBAT) + { + tmpADC_Common->CCR &= ~ADC_CCR_VBATE; + } + /* Enable the Temperature sensor and VREFINT channel*/ + tmpADC_Common->CCR |= ADC_CCR_TSVREFE; + + if (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) + { + /* Delay for temperature sensor stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configures the analog watchdog. + * @note Analog watchdog thresholds can be modified while ADC conversion + * is on going. + * In this case, some constraints must be taken into account: + * The programmed threshold values are effective from the next + * ADC EOC (end of unitary conversion). + * Considering that registers write delay may happen due to + * bus activity, this might cause an uncertainty on the + * effective timing of the new programmed threshold values. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param AnalogWDGConfig pointer to an ADC_AnalogWDGConfTypeDef structure + * that contains the configuration information of ADC analog watchdog. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef *hadc, ADC_AnalogWDGConfTypeDef *AnalogWDGConfig) +{ +#ifdef USE_FULL_ASSERT + uint32_t tmp = 0U; +#endif /* USE_FULL_ASSERT */ + + /* Check the parameters */ + assert_param(IS_ADC_ANALOG_WATCHDOG(AnalogWDGConfig->WatchdogMode)); + assert_param(IS_ADC_CHANNEL(AnalogWDGConfig->Channel)); + assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode)); + +#ifdef USE_FULL_ASSERT + tmp = ADC_GET_RESOLUTION(hadc); + assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->HighThreshold)); + assert_param(IS_ADC_RANGE(tmp, AnalogWDGConfig->LowThreshold)); +#endif /* USE_FULL_ASSERT */ + + /* Process locked */ + __HAL_LOCK(hadc); + + if (AnalogWDGConfig->ITMode == ENABLE) + { + /* Enable the ADC Analog watchdog interrupt */ + __HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD); + } + else + { + /* Disable the ADC Analog watchdog interrupt */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD); + } + + /* Clear AWDEN, JAWDEN and AWDSGL bits */ + hadc->Instance->CR1 &= ~(ADC_CR1_AWDSGL | ADC_CR1_JAWDEN | ADC_CR1_AWDEN); + + /* Set the analog watchdog enable mode */ + hadc->Instance->CR1 |= AnalogWDGConfig->WatchdogMode; + + /* Set the high threshold */ + hadc->Instance->HTR = AnalogWDGConfig->HighThreshold; + + /* Set the low threshold */ + hadc->Instance->LTR = AnalogWDGConfig->LowThreshold; + + /* Clear the Analog watchdog channel select bits */ + hadc->Instance->CR1 &= ~ADC_CR1_AWDCH; + + /* Set the Analog watchdog channel */ + hadc->Instance->CR1 |= (uint32_t)((uint16_t)(AnalogWDGConfig->Channel)); + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ADC_Exported_Functions_Group4 ADC Peripheral State functions + * @brief ADC Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State and errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the ADC state + (+) Check the ADC Error + +@endverbatim + * @{ + */ + +/** + * @brief return the ADC state + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL state + */ +uint32_t HAL_ADC_GetState(ADC_HandleTypeDef *hadc) +{ + /* Return ADC state */ + return hadc->State; +} + +/** + * @brief Return the ADC error code + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval ADC Error Code + */ +uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc) +{ + return hadc->ErrorCode; +} + +/** + * @} + */ + +/** @addtogroup ADC_Private_Functions + * @{ + */ + +/** + * @brief Initializes the ADCx peripheral according to the specified parameters + * in the ADC_InitStruct without initializing the ADC MSP. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +static void ADC_Init(ADC_HandleTypeDef *hadc) +{ + ADC_Common_TypeDef *tmpADC_Common; + + /* Set ADC parameters */ + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADCs and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Set the ADC clock prescaler */ + tmpADC_Common->CCR &= ~(ADC_CCR_ADCPRE); + tmpADC_Common->CCR |= hadc->Init.ClockPrescaler; + + /* Set ADC scan mode */ + hadc->Instance->CR1 &= ~(ADC_CR1_SCAN); + hadc->Instance->CR1 |= ADC_CR1_SCANCONV(hadc->Init.ScanConvMode); + + /* Set ADC resolution */ + hadc->Instance->CR1 &= ~(ADC_CR1_RES); + hadc->Instance->CR1 |= hadc->Init.Resolution; + + /* Set ADC data alignment */ + hadc->Instance->CR2 &= ~(ADC_CR2_ALIGN); + hadc->Instance->CR2 |= hadc->Init.DataAlign; + + /* Enable external trigger if trigger selection is different of software */ + /* start. */ + /* Note: This configuration keeps the hardware feature of parameter */ + /* ExternalTrigConvEdge "trigger edge none" equivalent to */ + /* software start. */ + if (hadc->Init.ExternalTrigConv != ADC_SOFTWARE_START) + { + /* Select external trigger to start conversion */ + hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL); + hadc->Instance->CR2 |= hadc->Init.ExternalTrigConv; + + /* Select external trigger polarity */ + hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN); + hadc->Instance->CR2 |= hadc->Init.ExternalTrigConvEdge; + } + else + { + /* Reset the external trigger */ + hadc->Instance->CR2 &= ~(ADC_CR2_EXTSEL); + hadc->Instance->CR2 &= ~(ADC_CR2_EXTEN); + } + + /* Enable or disable ADC continuous conversion mode */ + hadc->Instance->CR2 &= ~(ADC_CR2_CONT); + hadc->Instance->CR2 |= ADC_CR2_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode); + + if (hadc->Init.DiscontinuousConvMode != DISABLE) + { + assert_param(IS_ADC_REGULAR_DISC_NUMBER(hadc->Init.NbrOfDiscConversion)); + + /* Enable the selected ADC regular discontinuous mode */ + hadc->Instance->CR1 |= (uint32_t)ADC_CR1_DISCEN; + + /* Set the number of channels to be converted in discontinuous mode */ + hadc->Instance->CR1 &= ~(ADC_CR1_DISCNUM); + hadc->Instance->CR1 |= ADC_CR1_DISCONTINUOUS(hadc->Init.NbrOfDiscConversion); + } + else + { + /* Disable the selected ADC regular discontinuous mode */ + hadc->Instance->CR1 &= ~(ADC_CR1_DISCEN); + } + + /* Set ADC number of conversion */ + hadc->Instance->SQR1 &= ~(ADC_SQR1_L); + hadc->Instance->SQR1 |= ADC_SQR1(hadc->Init.NbrOfConversion); + + /* Enable or disable ADC DMA continuous request */ + hadc->Instance->CR2 &= ~(ADC_CR2_DDS); + hadc->Instance->CR2 |= ADC_CR2_DMAContReq((uint32_t)hadc->Init.DMAContinuousRequests); + + /* Enable or disable ADC end of conversion selection */ + hadc->Instance->CR2 &= ~(ADC_CR2_EOCS); + hadc->Instance->CR2 |= ADC_CR2_EOCSelection(hadc->Init.EOCSelection); +} + +/** + * @brief DMA transfer complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Retrieve ADC handle corresponding to current DMA handle */ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Update state machine on conversion status if not in error state */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) + { + /* Update ADC state machine */ + SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC); + + /* Determine whether any further conversion upcoming on group regular */ + /* by external trigger, continuous mode or scan sequence on going. */ + /* Note: On STM32F4, there is no independent flag of end of sequence. */ + /* The test of scan sequence on going is done either with scan */ + /* sequence disabled or with end of conversion flag set to */ + /* of end of sequence. */ + if (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE) && + (HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS))) + { + /* Disable ADC end of single conversion interrupt on group regular */ + /* Note: Overrun interrupt was enabled with EOC interrupt in */ + /* HAL_ADC_Start_IT(), but is not disabled here because can be used */ + /* by overrun IRQ process below. */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC); + + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Conversion complete callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ConvCpltCallback(hadc); +#else + HAL_ADC_ConvCpltCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + } + else /* DMA and-or internal error occurred */ + { + if ((hadc->State & HAL_ADC_STATE_ERROR_INTERNAL) != 0UL) + { + /* Call HAL ADC Error Callback function */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ErrorCallback(hadc); +#else + HAL_ADC_ErrorCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ + } + else + { + /* Call DMA error callback */ + hadc->DMA_Handle->XferErrorCallback(hdma); + } + } +} + +/** + * @brief DMA half transfer complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma) +{ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* Half conversion callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ConvHalfCpltCallback(hadc); +#else + HAL_ADC_ConvHalfCpltCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA error callback + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_DMAError(DMA_HandleTypeDef *hdma) +{ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + hadc->State = HAL_ADC_STATE_ERROR_DMA; + /* Set ADC error code to DMA error */ + hadc->ErrorCode |= HAL_ADC_ERROR_DMA; + /* Error callback */ +#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1) + hadc->ErrorCallback(hadc); +#else + HAL_ADC_ErrorCallback(hadc); +#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_ADC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c new file mode 100644 index 0000000..7db1993 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_adc_ex.c @@ -0,0 +1,1112 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_adc_ex.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the ADC extension peripheral: + * + Extended features functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + (#)Initialize the ADC low level resources by implementing the HAL_ADC_MspInit(): + (##) Enable the ADC interface clock using __HAL_RCC_ADC_CLK_ENABLE() + (##) ADC pins configuration + (+++) Enable the clock for the ADC GPIOs using the following function: + __HAL_RCC_GPIOx_CLK_ENABLE() + (+++) Configure these ADC pins in analog mode using HAL_GPIO_Init() + (##) In case of using interrupts (e.g. HAL_ADC_Start_IT()) + (+++) Configure the ADC interrupt priority using HAL_NVIC_SetPriority() + (+++) Enable the ADC IRQ handler using HAL_NVIC_EnableIRQ() + (+++) In ADC IRQ handler, call HAL_ADC_IRQHandler() + (##) In case of using DMA to control data transfer (e.g. HAL_ADC_Start_DMA()) + (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE() + (+++) Configure and enable two DMA streams stream for managing data + transfer from peripheral to memory (output stream) + (+++) Associate the initialized DMA handle to the ADC DMA handle + using __HAL_LINKDMA() + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the two DMA Streams. The output stream should have higher + priority than the input stream. + (#) Configure the ADC Prescaler, conversion resolution and data alignment + using the HAL_ADC_Init() function. + + (#) Configure the ADC Injected channels group features, use HAL_ADC_Init() + and HAL_ADC_ConfigChannel() functions. + + (#) Three operation modes are available within this driver: + + *** Polling mode IO operation *** + ================================= + [..] + (+) Start the ADC peripheral using HAL_ADCEx_InjectedStart() + (+) Wait for end of conversion using HAL_ADC_PollForConversion(), at this stage + user can specify the value of timeout according to his end application + (+) To read the ADC converted values, use the HAL_ADCEx_InjectedGetValue() function. + (+) Stop the ADC peripheral using HAL_ADCEx_InjectedStop() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Start the ADC peripheral using HAL_ADCEx_InjectedStart_IT() + (+) Use HAL_ADC_IRQHandler() called under ADC_IRQHandler() Interrupt subroutine + (+) At ADC end of conversion HAL_ADCEx_InjectedConvCpltCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADCEx_InjectedConvCpltCallback + (+) In case of ADC Error, HAL_ADCEx_InjectedErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_ADCEx_InjectedErrorCallback + (+) Stop the ADC peripheral using HAL_ADCEx_InjectedStop_IT() + + *** Multi mode ADCs Regular channels configuration *** + ====================================================== + [..] + (+) Select the Multi mode ADC regular channels features (dual or triple mode) + and configure the DMA mode using HAL_ADCEx_MultiModeConfigChannel() functions. + (+) Start the ADC peripheral using HAL_ADCEx_MultiModeStart_DMA(), at this stage the user specify the length + of data to be transferred at each end of conversion + (+) Read the ADCs converted values using the HAL_ADCEx_MultiModeGetValue() function. + + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup ADCEx ADCEx + * @brief ADC Extended driver modules + * @{ + */ + +#ifdef HAL_ADC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @addtogroup ADCEx_Private_Functions + * @{ + */ +/* Private function prototypes -----------------------------------------------*/ +static void ADC_MultiModeDMAConvCplt(DMA_HandleTypeDef *hdma); +static void ADC_MultiModeDMAError(DMA_HandleTypeDef *hdma); +static void ADC_MultiModeDMAHalfConvCplt(DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup ADCEx_Exported_Functions ADC Exported Functions + * @{ + */ + +/** @defgroup ADCEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Start conversion of injected channel. + (+) Stop conversion of injected channel. + (+) Start multimode and enable DMA transfer. + (+) Stop multimode and disable DMA transfer. + (+) Get result of injected channel conversion. + (+) Get result of multimode conversion. + (+) Configure injected channels. + (+) Configure multimode. + +@endverbatim + * @{ + */ + +/** + * @brief Enables the selected ADC software start conversion of the injected channels. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef *hadc) +{ + __IO uint32_t counter = 0U; + uint32_t tmp1 = 0U, tmp2 = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Enable the ADC peripheral */ + + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for ADC stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to injected group conversion results */ + /* - Set state bitfield related to injected operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC, + HAL_ADC_STATE_INJ_BUSY); + + /* Check if a regular conversion is ongoing */ + /* Note: On this device, there is no ADC error code fields related to */ + /* conversions on group injected only. In case of conversion on */ + /* going on group regular, no error code is reset. */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Clear injected group conversion flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Check if Multimode enabled */ + if (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_MULTI)) + { + tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); + tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); + if (tmp1 && tmp2) + { + /* Enable the selected ADC software conversion for injected group */ + hadc->Instance->CR2 |= ADC_CR2_JSWSTART; + } + } + else + { + tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); + tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); + if ((hadc->Instance == ADC1) && tmp1 && tmp2) + { + /* Enable the selected ADC software conversion for injected group */ + hadc->Instance->CR2 |= ADC_CR2_JSWSTART; + } + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Enables the interrupt and starts ADC conversion of injected channels. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef *hadc) +{ + __IO uint32_t counter = 0U; + uint32_t tmp1 = 0U, tmp2 = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Enable the ADC peripheral */ + + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for ADC stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to injected group conversion results */ + /* - Set state bitfield related to injected operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC, + HAL_ADC_STATE_INJ_BUSY); + + /* Check if a regular conversion is ongoing */ + /* Note: On this device, there is no ADC error code fields related to */ + /* conversions on group injected only. In case of conversion on */ + /* going on group regular, no error code is reset. */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Clear injected group conversion flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); + + /* Enable end of conversion interrupt for injected channels */ + __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Check if Multimode enabled */ + if (HAL_IS_BIT_CLR(tmpADC_Common->CCR, ADC_CCR_MULTI)) + { + tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); + tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); + if (tmp1 && tmp2) + { + /* Enable the selected ADC software conversion for injected group */ + hadc->Instance->CR2 |= ADC_CR2_JSWSTART; + } + } + else + { + tmp1 = HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_JEXTEN); + tmp2 = HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO); + if ((hadc->Instance == ADC1) && tmp1 && tmp2) + { + /* Enable the selected ADC software conversion for injected group */ + hadc->Instance->CR2 |= ADC_CR2_JSWSTART; + } + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop conversion of injected channels. Disable ADC peripheral if + * no regular conversion is on going. + * @note If ADC must be disabled and if conversion is on going on + * regular group, function HAL_ADC_Stop must be used to stop both + * injected and regular groups, and disable the ADC. + * @note If injected group mode auto-injection is enabled, + * function HAL_ADC_Stop must be used. + * @note In case of auto-injection mode, HAL_ADC_Stop must be used. + * @param hadc ADC handle + * @retval None + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion and disable ADC peripheral */ + /* Conditioned to: */ + /* - No conversion on the other group (regular group) is intended to */ + /* continue (injected and regular groups stop conversion and ADC disable */ + /* are common) */ + /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */ + if (((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) && + HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO)) + { + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); + + tmp_hal_status = HAL_ERROR; + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +/** + * @brief Poll for injected conversion complete + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param Timeout Timeout value in millisecond. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check End of conversion flag */ + while (!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC))) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* New check to avoid false timeout detection in case of preemption */ + if (!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_JEOC))) + { + hadc->State = HAL_ADC_STATE_TIMEOUT; + /* Process unlocked */ + __HAL_UNLOCK(hadc); + return HAL_TIMEOUT; + } + } + } + } + + /* Clear injected group conversion flag */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC); + + /* Update ADC state machine */ + SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC); + + /* Determine whether any further conversion upcoming on group injected */ + /* by external trigger, continuous mode or scan sequence on going. */ + /* Note: On STM32F4, there is no independent flag of end of sequence. */ + /* The test of scan sequence on going is done either with scan */ + /* sequence disabled or with end of conversion flag set to */ + /* of end of sequence. */ + if (ADC_IS_SOFTWARE_START_INJECTED(hadc) && + (HAL_IS_BIT_CLR(hadc->Instance->JSQR, ADC_JSQR_JL) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS)) && + (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) && + (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE)))) + { + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Return ADC state */ + return HAL_OK; +} + +/** + * @brief Stop conversion of injected channels, disable interruption of + * end-of-conversion. Disable ADC peripheral if no regular conversion + * is on going. + * @note If ADC must be disabled and if conversion is on going on + * regular group, function HAL_ADC_Stop must be used to stop both + * injected and regular groups, and disable the ADC. + * @note If injected group mode auto-injection is enabled, + * function HAL_ADC_Stop must be used. + * @param hadc ADC handle + * @retval None + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion and disable ADC peripheral */ + /* Conditioned to: */ + /* - No conversion on the other group (regular group) is intended to */ + /* continue (injected and regular groups stop conversion and ADC disable */ + /* are common) */ + /* - In case of auto-injection mode, HAL_ADC_Stop must be used. */ + if (((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) && + HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO)) + { + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Disable ADC end of conversion interrupt for injected channels */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC); + + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG); + + tmp_hal_status = HAL_ERROR; + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +/** + * @brief Gets the converted value from data register of injected channel. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param InjectedRank the ADC injected rank. + * This parameter can be one of the following values: + * @arg ADC_INJECTED_RANK_1: Injected Channel1 selected + * @arg ADC_INJECTED_RANK_2: Injected Channel2 selected + * @arg ADC_INJECTED_RANK_3: Injected Channel3 selected + * @arg ADC_INJECTED_RANK_4: Injected Channel4 selected + * @retval None + */ +uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef *hadc, uint32_t InjectedRank) +{ + __IO uint32_t tmp = 0U; + + /* Check the parameters */ + assert_param(IS_ADC_INJECTED_RANK(InjectedRank)); + + /* Clear injected group conversion flag to have similar behaviour as */ + /* regular group: reading data register also clears end of conversion flag. */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC); + + /* Return the selected ADC converted value */ + switch (InjectedRank) + { + case ADC_INJECTED_RANK_4: + { + tmp = hadc->Instance->JDR4; + } + break; + case ADC_INJECTED_RANK_3: + { + tmp = hadc->Instance->JDR3; + } + break; + case ADC_INJECTED_RANK_2: + { + tmp = hadc->Instance->JDR2; + } + break; + case ADC_INJECTED_RANK_1: + { + tmp = hadc->Instance->JDR1; + } + break; + default: + break; + } + return tmp; +} + +/** + * @brief Enables ADC DMA request after last transfer (Multi-ADC mode) and enables ADC peripheral + * + * @note Caution: This function must be used only with the ADC master. + * + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param pData Pointer to buffer in which transferred from ADC peripheral to memory will be stored. + * @param Length The length of data to be transferred from ADC peripheral to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length) +{ + __IO uint32_t counter = 0U; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode)); + assert_param(IS_ADC_EXT_TRIG_EDGE(hadc->Init.ExternalTrigConvEdge)); + assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DMAContinuousRequests)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Check if ADC peripheral is disabled in order to enable it and wait during + Tstab time the ADC's stabilization */ + if ((hadc->Instance->CR2 & ADC_CR2_ADON) != ADC_CR2_ADON) + { + /* Enable the Peripheral */ + __HAL_ADC_ENABLE(hadc); + + /* Delay for temperature sensor stabilization time */ + /* Compute number of CPU cycles to wait for */ + counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U)); + while (counter != 0U) + { + counter--; + } + } + + /* Start conversion if ADC is effectively enabled */ + if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Set ADC state */ + /* - Clear state bitfield related to regular group conversion results */ + /* - Set state bitfield related to regular group operation */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR, + HAL_ADC_STATE_REG_BUSY); + + /* If conversions on group regular are also triggering group injected, */ + /* update ADC state. */ + if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET) + { + ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY); + } + + /* State machine update: Check if an injected conversion is ongoing */ + if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + /* Reset ADC error code fields related to conversions on group regular */ + CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA)); + } + else + { + /* Reset ADC all error code fields */ + ADC_CLEAR_ERRORCODE(hadc); + } + + /* Process unlocked */ + /* Unlock before starting ADC conversions: in case of potential */ + /* interruption, to let the process to ADC IRQ Handler. */ + __HAL_UNLOCK(hadc); + + /* Set the DMA transfer complete callback */ + hadc->DMA_Handle->XferCpltCallback = ADC_MultiModeDMAConvCplt; + + /* Set the DMA half transfer complete callback */ + hadc->DMA_Handle->XferHalfCpltCallback = ADC_MultiModeDMAHalfConvCplt; + + /* Set the DMA error callback */ + hadc->DMA_Handle->XferErrorCallback = ADC_MultiModeDMAError ; + + /* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */ + /* start (in case of SW start): */ + + /* Clear regular group conversion flag and overrun flag */ + /* (To ensure of no unknown state from potential previous ADC operations) */ + __HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC); + + /* Enable ADC overrun interrupt */ + __HAL_ADC_ENABLE_IT(hadc, ADC_IT_OVR); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + if (hadc->Init.DMAContinuousRequests != DISABLE) + { + /* Enable the selected ADC DMA request after last transfer */ + tmpADC_Common->CCR |= ADC_CCR_DDS; + } + else + { + /* Disable the selected ADC EOC rising on each regular channel conversion */ + tmpADC_Common->CCR &= ~ADC_CCR_DDS; + } + + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&tmpADC_Common->CDR, (uint32_t)pData, Length); + + /* if no external trigger present enable software conversion of regular channels */ + if ((hadc->Instance->CR2 & ADC_CR2_EXTEN) == RESET) + { + /* Enable the selected ADC software conversion for regular group */ + hadc->Instance->CR2 |= (uint32_t)ADC_CR2_SWSTART; + } + } + else + { + /* Update ADC state machine to error */ + SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL); + + /* Set ADC error code to ADC IP internal error */ + SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Disables ADC DMA (multi-ADC mode) and disables ADC peripheral + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef *hadc) +{ + HAL_StatusTypeDef tmp_hal_status = HAL_OK; + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Stop potential conversion on going, on regular and injected groups */ + /* Disable ADC peripheral */ + __HAL_ADC_DISABLE(hadc); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Check if ADC is effectively disabled */ + if (HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_ADON)) + { + /* Disable the selected ADC DMA mode for multimode */ + tmpADC_Common->CCR &= ~ADC_CCR_DDS; + + /* Disable the DMA channel (in case of DMA in circular mode or stop while */ + /* DMA transfer is on going) */ + tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle); + + /* Disable ADC overrun interrupt */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_OVR); + + /* Set ADC state */ + ADC_STATE_CLR_SET(hadc->State, + HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY, + HAL_ADC_STATE_READY); + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return tmp_hal_status; +} + +/** + * @brief Returns the last ADC1, ADC2 and ADC3 regular conversions results + * data in the selected multi mode. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval The converted data value. + */ +uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef *hadc) +{ + ADC_Common_TypeDef *tmpADC_Common; + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Return the multi mode conversion value */ + return tmpADC_Common->CDR; +} + +/** + * @brief Injected conversion complete callback in non blocking mode + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @retval None + */ +__weak void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hadc); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ADC_InjectedConvCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Configures for the selected ADC injected channel its corresponding + * rank in the sequencer and its sample time. + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param sConfigInjected ADC configuration structure for injected channel. + * @retval None + */ +HAL_StatusTypeDef HAL_ADCEx_InjectedConfigChannel(ADC_HandleTypeDef *hadc, ADC_InjectionConfTypeDef *sConfigInjected) +{ + +#ifdef USE_FULL_ASSERT + uint32_t tmp = 0U; + +#endif /* USE_FULL_ASSERT */ + + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_ADC_CHANNEL(sConfigInjected->InjectedChannel)); + assert_param(IS_ADC_INJECTED_RANK(sConfigInjected->InjectedRank)); + assert_param(IS_ADC_SAMPLE_TIME(sConfigInjected->InjectedSamplingTime)); + assert_param(IS_ADC_EXT_INJEC_TRIG(sConfigInjected->ExternalTrigInjecConv)); + assert_param(IS_ADC_INJECTED_LENGTH(sConfigInjected->InjectedNbrOfConversion)); + assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->AutoInjectedConv)); + assert_param(IS_FUNCTIONAL_STATE(sConfigInjected->InjectedDiscontinuousConvMode)); + +#ifdef USE_FULL_ASSERT + tmp = ADC_GET_RESOLUTION(hadc); + assert_param(IS_ADC_RANGE(tmp, sConfigInjected->InjectedOffset)); +#endif /* USE_FULL_ASSERT */ + + if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START) + { + assert_param(IS_ADC_EXT_INJEC_TRIG_EDGE(sConfigInjected->ExternalTrigInjecConvEdge)); + } + + /* Process locked */ + __HAL_LOCK(hadc); + + /* if ADC_Channel_10 ... ADC_Channel_18 is selected */ + if (sConfigInjected->InjectedChannel > ADC_CHANNEL_9) + { + /* Clear the old sample time */ + hadc->Instance->SMPR1 &= ~ADC_SMPR1(ADC_SMPR1_SMP10, sConfigInjected->InjectedChannel); + + /* Set the new sample time */ + hadc->Instance->SMPR1 |= ADC_SMPR1(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel); + } + else /* ADC_Channel include in ADC_Channel_[0..9] */ + { + /* Clear the old sample time */ + hadc->Instance->SMPR2 &= ~ADC_SMPR2(ADC_SMPR2_SMP0, sConfigInjected->InjectedChannel); + + /* Set the new sample time */ + hadc->Instance->SMPR2 |= ADC_SMPR2(sConfigInjected->InjectedSamplingTime, sConfigInjected->InjectedChannel); + } + + /*---------------------------- ADCx JSQR Configuration -----------------*/ + hadc->Instance->JSQR &= ~(ADC_JSQR_JL); + hadc->Instance->JSQR |= ADC_SQR1(sConfigInjected->InjectedNbrOfConversion); + + /* Rank configuration */ + + /* Clear the old SQx bits for the selected rank */ + hadc->Instance->JSQR &= ~ADC_JSQR(ADC_JSQR_JSQ1, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion); + + /* Set the SQx bits for the selected rank */ + hadc->Instance->JSQR |= ADC_JSQR(sConfigInjected->InjectedChannel, sConfigInjected->InjectedRank, sConfigInjected->InjectedNbrOfConversion); + + /* Enable external trigger if trigger selection is different of software */ + /* start. */ + /* Note: This configuration keeps the hardware feature of parameter */ + /* ExternalTrigConvEdge "trigger edge none" equivalent to */ + /* software start. */ + if (sConfigInjected->ExternalTrigInjecConv != ADC_INJECTED_SOFTWARE_START) + { + /* Select external trigger to start conversion */ + hadc->Instance->CR2 &= ~(ADC_CR2_JEXTSEL); + hadc->Instance->CR2 |= sConfigInjected->ExternalTrigInjecConv; + + /* Select external trigger polarity */ + hadc->Instance->CR2 &= ~(ADC_CR2_JEXTEN); + hadc->Instance->CR2 |= sConfigInjected->ExternalTrigInjecConvEdge; + } + else + { + /* Reset the external trigger */ + hadc->Instance->CR2 &= ~(ADC_CR2_JEXTSEL); + hadc->Instance->CR2 &= ~(ADC_CR2_JEXTEN); + } + + if (sConfigInjected->AutoInjectedConv != DISABLE) + { + /* Enable the selected ADC automatic injected group conversion */ + hadc->Instance->CR1 |= ADC_CR1_JAUTO; + } + else + { + /* Disable the selected ADC automatic injected group conversion */ + hadc->Instance->CR1 &= ~(ADC_CR1_JAUTO); + } + + if (sConfigInjected->InjectedDiscontinuousConvMode != DISABLE) + { + /* Enable the selected ADC injected discontinuous mode */ + hadc->Instance->CR1 |= ADC_CR1_JDISCEN; + } + else + { + /* Disable the selected ADC injected discontinuous mode */ + hadc->Instance->CR1 &= ~(ADC_CR1_JDISCEN); + } + + switch (sConfigInjected->InjectedRank) + { + case 1U: + /* Set injected channel 1 offset */ + hadc->Instance->JOFR1 &= ~(ADC_JOFR1_JOFFSET1); + hadc->Instance->JOFR1 |= sConfigInjected->InjectedOffset; + break; + case 2U: + /* Set injected channel 2 offset */ + hadc->Instance->JOFR2 &= ~(ADC_JOFR2_JOFFSET2); + hadc->Instance->JOFR2 |= sConfigInjected->InjectedOffset; + break; + case 3U: + /* Set injected channel 3 offset */ + hadc->Instance->JOFR3 &= ~(ADC_JOFR3_JOFFSET3); + hadc->Instance->JOFR3 |= sConfigInjected->InjectedOffset; + break; + default: + /* Set injected channel 4 offset */ + hadc->Instance->JOFR4 &= ~(ADC_JOFR4_JOFFSET4); + hadc->Instance->JOFR4 |= sConfigInjected->InjectedOffset; + break; + } + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* if ADC1 Channel_18 is selected enable VBAT Channel */ + if ((hadc->Instance == ADC1) && (sConfigInjected->InjectedChannel == ADC_CHANNEL_VBAT)) + { + /* Enable the VBAT channel*/ + tmpADC_Common->CCR |= ADC_CCR_VBATE; + } + + /* if ADC1 Channel_16 or Channel_17 is selected enable TSVREFE Channel(Temperature sensor and VREFINT) */ + if ((hadc->Instance == ADC1) && ((sConfigInjected->InjectedChannel == ADC_CHANNEL_TEMPSENSOR) || (sConfigInjected->InjectedChannel == ADC_CHANNEL_VREFINT))) + { + /* Enable the TSVREFE channel*/ + tmpADC_Common->CCR |= ADC_CCR_TSVREFE; + } + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configures the ADC multi-mode + * @param hadc pointer to a ADC_HandleTypeDef structure that contains + * the configuration information for the specified ADC. + * @param multimode pointer to an ADC_MultiModeTypeDef structure that contains + * the configuration information for multimode. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef *hadc, ADC_MultiModeTypeDef *multimode) +{ + + ADC_Common_TypeDef *tmpADC_Common; + + /* Check the parameters */ + assert_param(IS_ADC_MODE(multimode->Mode)); + assert_param(IS_ADC_DMA_ACCESS_MODE(multimode->DMAAccessMode)); + assert_param(IS_ADC_SAMPLING_DELAY(multimode->TwoSamplingDelay)); + + /* Process locked */ + __HAL_LOCK(hadc); + + /* Pointer to the common control register to which is belonging hadc */ + /* (Depending on STM32F4 product, there may be up to 3 ADC and 1 common */ + /* control register) */ + tmpADC_Common = ADC_COMMON_REGISTER(hadc); + + /* Set ADC mode */ + tmpADC_Common->CCR &= ~(ADC_CCR_MULTI); + tmpADC_Common->CCR |= multimode->Mode; + + /* Set the ADC DMA access mode */ + tmpADC_Common->CCR &= ~(ADC_CCR_DMA); + tmpADC_Common->CCR |= multimode->DMAAccessMode; + + /* Set delay between two sampling phases */ + tmpADC_Common->CCR &= ~(ADC_CCR_DELAY); + tmpADC_Common->CCR |= multimode->TwoSamplingDelay; + + /* Process unlocked */ + __HAL_UNLOCK(hadc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** + * @brief DMA transfer complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_MultiModeDMAConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Retrieve ADC handle corresponding to current DMA handle */ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Update state machine on conversion status if not in error state */ + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA)) + { + /* Update ADC state machine */ + SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC); + + /* Determine whether any further conversion upcoming on group regular */ + /* by external trigger, continuous mode or scan sequence on going. */ + /* Note: On STM32F4, there is no independent flag of end of sequence. */ + /* The test of scan sequence on going is done either with scan */ + /* sequence disabled or with end of conversion flag set to */ + /* of end of sequence. */ + if (ADC_IS_SOFTWARE_START_REGULAR(hadc) && + (hadc->Init.ContinuousConvMode == DISABLE) && + (HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) || + HAL_IS_BIT_CLR(hadc->Instance->CR2, ADC_CR2_EOCS))) + { + /* Disable ADC end of single conversion interrupt on group regular */ + /* Note: Overrun interrupt was enabled with EOC interrupt in */ + /* HAL_ADC_Start_IT(), but is not disabled here because can be used */ + /* by overrun IRQ process below. */ + __HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC); + + /* Set ADC state */ + CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY); + + if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY)) + { + SET_BIT(hadc->State, HAL_ADC_STATE_READY); + } + } + + /* Conversion complete callback */ + HAL_ADC_ConvCpltCallback(hadc); + } + else + { + /* Call DMA error callback */ + hadc->DMA_Handle->XferErrorCallback(hdma); + } +} + +/** + * @brief DMA half transfer complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_MultiModeDMAHalfConvCplt(DMA_HandleTypeDef *hdma) +{ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* Conversion complete callback */ + HAL_ADC_ConvHalfCpltCallback(hadc); +} + +/** + * @brief DMA error callback + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void ADC_MultiModeDMAError(DMA_HandleTypeDef *hdma) +{ + ADC_HandleTypeDef *hadc = (ADC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + hadc->State = HAL_ADC_STATE_ERROR_DMA; + /* Set ADC error code to DMA error */ + hadc->ErrorCode |= HAL_ADC_ERROR_DMA; + HAL_ADC_ErrorCallback(hadc); +} + +/** + * @} + */ + +#endif /* HAL_ADC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c new file mode 100644 index 0000000..b9bb575 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c @@ -0,0 +1,2466 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_can.c + * @author MCD Application Team + * @brief CAN HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Controller Area Network (CAN) peripheral: + * + Initialization and de-initialization functions + * + Configuration functions + * + Control functions + * + Interrupts management + * + Callbacks functions + * + Peripheral State and Error 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 ##### + ============================================================================== + [..] + (#) Initialize the CAN low level resources by implementing the + HAL_CAN_MspInit(): + (++) Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE() + (++) Configure CAN pins + (+++) Enable the clock for the CAN GPIOs + (+++) Configure CAN pins as alternate function open-drain + (++) In case of using interrupts (e.g. HAL_CAN_ActivateNotification()) + (+++) Configure the CAN interrupt priority using + HAL_NVIC_SetPriority() + (+++) Enable the CAN IRQ handler using HAL_NVIC_EnableIRQ() + (+++) In CAN IRQ handler, call HAL_CAN_IRQHandler() + + (#) Initialize the CAN peripheral using HAL_CAN_Init() function. This + function resorts to HAL_CAN_MspInit() for low-level initialization. + + (#) Configure the reception filters using the following configuration + functions: + (++) HAL_CAN_ConfigFilter() + + (#) Start the CAN module using HAL_CAN_Start() function. At this level + the node is active on the bus: it receive messages, and can send + messages. + + (#) To manage messages transmission, the following Tx control functions + can be used: + (++) HAL_CAN_AddTxMessage() to request transmission of a new + message. + (++) HAL_CAN_AbortTxRequest() to abort transmission of a pending + message. + (++) HAL_CAN_GetTxMailboxesFreeLevel() to get the number of free Tx + mailboxes. + (++) HAL_CAN_IsTxMessagePending() to check if a message is pending + in a Tx mailbox. + (++) HAL_CAN_GetTxTimestamp() to get the timestamp of Tx message + sent, if time triggered communication mode is enabled. + + (#) When a message is received into the CAN Rx FIFOs, it can be retrieved + using the HAL_CAN_GetRxMessage() function. The function + HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are + stored in the Rx Fifo. + + (#) Calling the HAL_CAN_Stop() function stops the CAN module. + + (#) The deinitialization is achieved with HAL_CAN_DeInit() function. + + + *** Polling mode operation *** + ============================== + [..] + (#) Reception: + (++) Monitor reception of message using HAL_CAN_GetRxFifoFillLevel() + until at least one message is received. + (++) Then get the message using HAL_CAN_GetRxMessage(). + + (#) Transmission: + (++) Monitor the Tx mailboxes availability until at least one Tx + mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel(). + (++) Then request transmission of a message using + HAL_CAN_AddTxMessage(). + + + *** Interrupt mode operation *** + ================================ + [..] + (#) Notifications are activated using HAL_CAN_ActivateNotification() + function. Then, the process can be controlled through the + available user callbacks: HAL_CAN_xxxCallback(), using same APIs + HAL_CAN_GetRxMessage() and HAL_CAN_AddTxMessage(). + + (#) Notifications can be deactivated using + HAL_CAN_DeactivateNotification() function. + + (#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and + CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig + the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and + HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options + here. + (++) Directly get the Rx message in the callback, using + HAL_CAN_GetRxMessage(). + (++) Or deactivate the notification in the callback without + getting the Rx message. The Rx message can then be got later + using HAL_CAN_GetRxMessage(). Once the Rx message have been + read, the notification can be activated again. + + + *** Sleep mode *** + ================== + [..] + (#) The CAN peripheral can be put in sleep mode (low power), using + HAL_CAN_RequestSleep(). The sleep mode will be entered as soon as the + current CAN activity (transmission or reception of a CAN frame) will + be completed. + + (#) A notification can be activated to be informed when the sleep mode + will be entered. + + (#) It can be checked if the sleep mode is entered using + HAL_CAN_IsSleepActive(). + Note that the CAN state (accessible from the API HAL_CAN_GetState()) + is HAL_CAN_STATE_SLEEP_PENDING as soon as the sleep mode request is + submitted (the sleep mode is not yet entered), and become + HAL_CAN_STATE_SLEEP_ACTIVE when the sleep mode is effective. + + (#) The wake-up from sleep mode can be triggered by two ways: + (++) Using HAL_CAN_WakeUp(). When returning from this function, + the sleep mode is exited (if return status is HAL_OK). + (++) When a start of Rx CAN frame is detected by the CAN peripheral, + if automatic wake up mode is enabled. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_CAN_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_CAN_RegisterCallback() to register an interrupt callback. + + Function HAL_CAN_RegisterCallback() allows to register following callbacks: + (+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback. + (+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback. + (+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback. + (+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback. + (+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback. + (+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback. + (+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback. + (+) RxFifo0FullCallback : Rx Fifo 0 Full Callback. + (+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback. + (+) RxFifo1FullCallback : Rx Fifo 1 Full Callback. + (+) SleepCallback : Sleep Callback. + (+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback. + (+) ErrorCallback : Error Callback. + (+) MspInitCallback : CAN MspInit. + (+) MspDeInitCallback : CAN MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_CAN_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_CAN_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback. + (+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback. + (+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback. + (+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback. + (+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback. + (+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback. + (+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback. + (+) RxFifo0FullCallback : Rx Fifo 0 Full Callback. + (+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback. + (+) RxFifo1FullCallback : Rx Fifo 1 Full Callback. + (+) SleepCallback : Sleep Callback. + (+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback. + (+) ErrorCallback : Error Callback. + (+) MspInitCallback : CAN MspInit. + (+) MspDeInitCallback : CAN MspDeInit. + + By default, after the HAL_CAN_Init() and when the state is HAL_CAN_STATE_RESET, + all callbacks are set to the corresponding weak functions: + example HAL_CAN_ErrorCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_CAN_Init()/ HAL_CAN_DeInit() only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_CAN_Init()/ HAL_CAN_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_CAN_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_CAN_STATE_READY or HAL_CAN_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_CAN_RegisterCallback() before calling HAL_CAN_DeInit() + or HAL_CAN_Init() function. + + When The compilation define USE_HAL_CAN_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined(CAN1) + +/** @defgroup CAN CAN + * @brief CAN driver modules + * @{ + */ + +#ifdef HAL_CAN_MODULE_ENABLED + +#ifdef HAL_CAN_LEGACY_MODULE_ENABLED +#error "The CAN driver cannot be used with its legacy, Please enable only one CAN module at once" +#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup CAN_Private_Constants CAN Private Constants + * @{ + */ +#define CAN_TIMEOUT_VALUE 10U +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup CAN_Exported_Functions CAN Exported Functions + * @{ + */ + +/** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de-initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) HAL_CAN_Init : Initialize and configure the CAN. + (+) HAL_CAN_DeInit : De-initialize the CAN. + (+) HAL_CAN_MspInit : Initialize the CAN MSP. + (+) HAL_CAN_MspDeInit : DeInitialize the CAN MSP. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the CAN peripheral according to the specified + * parameters in the CAN_InitStruct. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan) +{ + uint32_t tickstart; + + /* Check CAN handle */ + if (hcan == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TimeTriggeredMode)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoBusOff)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoWakeUp)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoRetransmission)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ReceiveFifoLocked)); + assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TransmitFifoPriority)); + assert_param(IS_CAN_MODE(hcan->Init.Mode)); + assert_param(IS_CAN_SJW(hcan->Init.SyncJumpWidth)); + assert_param(IS_CAN_BS1(hcan->Init.TimeSeg1)); + assert_param(IS_CAN_BS2(hcan->Init.TimeSeg2)); + assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler)); + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + if (hcan->State == HAL_CAN_STATE_RESET) + { + /* Reset callbacks to legacy functions */ + hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback; /* Legacy weak RxFifo0MsgPendingCallback */ + hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback; /* Legacy weak RxFifo0FullCallback */ + hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback; /* Legacy weak RxFifo1MsgPendingCallback */ + hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback; /* Legacy weak RxFifo1FullCallback */ + hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback; /* Legacy weak TxMailbox0CompleteCallback */ + hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback; /* Legacy weak TxMailbox1CompleteCallback */ + hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback; /* Legacy weak TxMailbox2CompleteCallback */ + hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback; /* Legacy weak TxMailbox0AbortCallback */ + hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback; /* Legacy weak TxMailbox1AbortCallback */ + hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback; /* Legacy weak TxMailbox2AbortCallback */ + hcan->SleepCallback = HAL_CAN_SleepCallback; /* Legacy weak SleepCallback */ + hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback; /* Legacy weak WakeUpFromRxMsgCallback */ + hcan->ErrorCallback = HAL_CAN_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hcan->MspInitCallback == NULL) + { + hcan->MspInitCallback = HAL_CAN_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware: CLOCK, NVIC */ + hcan->MspInitCallback(hcan); + } + +#else + if (hcan->State == HAL_CAN_STATE_RESET) + { + /* Init the low level hardware: CLOCK, NVIC */ + HAL_CAN_MspInit(hcan); + } +#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ + + /* Request initialisation */ + SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait initialisation acknowledge */ + while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U) + { + if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Exit from sleep mode */ + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check Sleep mode leave acknowledge */ + while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) + { + if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Set the time triggered communication mode */ + if (hcan->Init.TimeTriggeredMode == ENABLE) + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_TTCM); + } + else + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TTCM); + } + + /* Set the automatic bus-off management */ + if (hcan->Init.AutoBusOff == ENABLE) + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_ABOM); + } + else + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_ABOM); + } + + /* Set the automatic wake-up mode */ + if (hcan->Init.AutoWakeUp == ENABLE) + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_AWUM); + } + else + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_AWUM); + } + + /* Set the automatic retransmission */ + if (hcan->Init.AutoRetransmission == ENABLE) + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_NART); + } + else + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_NART); + } + + /* Set the receive FIFO locked mode */ + if (hcan->Init.ReceiveFifoLocked == ENABLE) + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_RFLM); + } + else + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_RFLM); + } + + /* Set the transmit FIFO priority */ + if (hcan->Init.TransmitFifoPriority == ENABLE) + { + SET_BIT(hcan->Instance->MCR, CAN_MCR_TXFP); + } + else + { + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TXFP); + } + + /* Set the bit timing register */ + WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode | + hcan->Init.SyncJumpWidth | + hcan->Init.TimeSeg1 | + hcan->Init.TimeSeg2 | + (hcan->Init.Prescaler - 1U))); + + /* Initialize the error code */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Initialize the CAN state */ + hcan->State = HAL_CAN_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Deinitializes the CAN peripheral registers to their default + * reset values. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan) +{ + /* Check CAN handle */ + if (hcan == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); + + /* Stop the CAN module */ + (void)HAL_CAN_Stop(hcan); + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + if (hcan->MspDeInitCallback == NULL) + { + hcan->MspDeInitCallback = HAL_CAN_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: CLOCK, NVIC */ + hcan->MspDeInitCallback(hcan); + +#else + /* DeInit the low level hardware: CLOCK, NVIC */ + HAL_CAN_MspDeInit(hcan); +#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ + + /* Reset the CAN peripheral */ + SET_BIT(hcan->Instance->MCR, CAN_MCR_RESET); + + /* Reset the CAN ErrorCode */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the CAN MSP. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes the CAN MSP. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_MspDeInit could be implemented in the user file + */ +} + +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 +/** + * @brief Register a CAN CallBack. + * To be used instead of the weak predefined callback + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for CAN module + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID + * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID + * @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID + * @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID + * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID + * @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID, + void (* pCallback)(CAN_HandleTypeDef *_hcan)) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + if (hcan->State == HAL_CAN_STATE_READY) + { + switch (CallbackID) + { + case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID : + hcan->TxMailbox0CompleteCallback = pCallback; + break; + + case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID : + hcan->TxMailbox1CompleteCallback = pCallback; + break; + + case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID : + hcan->TxMailbox2CompleteCallback = pCallback; + break; + + case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID : + hcan->TxMailbox0AbortCallback = pCallback; + break; + + case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID : + hcan->TxMailbox1AbortCallback = pCallback; + break; + + case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID : + hcan->TxMailbox2AbortCallback = pCallback; + break; + + case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID : + hcan->RxFifo0MsgPendingCallback = pCallback; + break; + + case HAL_CAN_RX_FIFO0_FULL_CB_ID : + hcan->RxFifo0FullCallback = pCallback; + break; + + case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID : + hcan->RxFifo1MsgPendingCallback = pCallback; + break; + + case HAL_CAN_RX_FIFO1_FULL_CB_ID : + hcan->RxFifo1FullCallback = pCallback; + break; + + case HAL_CAN_SLEEP_CB_ID : + hcan->SleepCallback = pCallback; + break; + + case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID : + hcan->WakeUpFromRxMsgCallback = pCallback; + break; + + case HAL_CAN_ERROR_CB_ID : + hcan->ErrorCallback = pCallback; + break; + + case HAL_CAN_MSPINIT_CB_ID : + hcan->MspInitCallback = pCallback; + break; + + case HAL_CAN_MSPDEINIT_CB_ID : + hcan->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcan->State == HAL_CAN_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CAN_MSPINIT_CB_ID : + hcan->MspInitCallback = pCallback; + break; + + case HAL_CAN_MSPDEINIT_CB_ID : + hcan->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister a CAN CallBack. + * CAN callback is redirected to the weak predefined callback + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for CAN module + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID + * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID + * @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID + * @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID + * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID + * @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (hcan->State == HAL_CAN_STATE_READY) + { + switch (CallbackID) + { + case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID : + hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback; + break; + + case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID : + hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback; + break; + + case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID : + hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback; + break; + + case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID : + hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback; + break; + + case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID : + hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback; + break; + + case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID : + hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback; + break; + + case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID : + hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback; + break; + + case HAL_CAN_RX_FIFO0_FULL_CB_ID : + hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback; + break; + + case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID : + hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback; + break; + + case HAL_CAN_RX_FIFO1_FULL_CB_ID : + hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback; + break; + + case HAL_CAN_SLEEP_CB_ID : + hcan->SleepCallback = HAL_CAN_SleepCallback; + break; + + case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID : + hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback; + break; + + case HAL_CAN_ERROR_CB_ID : + hcan->ErrorCallback = HAL_CAN_ErrorCallback; + break; + + case HAL_CAN_MSPINIT_CB_ID : + hcan->MspInitCallback = HAL_CAN_MspInit; + break; + + case HAL_CAN_MSPDEINIT_CB_ID : + hcan->MspDeInitCallback = HAL_CAN_MspDeInit; + break; + + default : + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcan->State == HAL_CAN_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CAN_MSPINIT_CB_ID : + hcan->MspInitCallback = HAL_CAN_MspInit; + break; + + case HAL_CAN_MSPDEINIT_CB_ID : + hcan->MspDeInitCallback = HAL_CAN_MspDeInit; + break; + + default : + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group2 Configuration functions + * @brief Configuration functions. + * +@verbatim + ============================================================================== + ##### Configuration functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) HAL_CAN_ConfigFilter : Configure the CAN reception filters + +@endverbatim + * @{ + */ + +/** + * @brief Configures the CAN reception filter according to the specified + * parameters in the CAN_FilterInitStruct. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param sFilterConfig pointer to a CAN_FilterTypeDef structure that + * contains the filter configuration information. + * @retval None + */ +HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig) +{ + uint32_t filternbrbitpos; + CAN_TypeDef *can_ip = hcan->Instance; + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check the parameters */ + assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdHigh)); + assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdLow)); + assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdHigh)); + assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdLow)); + assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode)); + assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale)); + assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment)); + assert_param(IS_CAN_FILTER_ACTIVATION(sFilterConfig->FilterActivation)); + +#if defined(CAN3) + /* Check the CAN instance */ + if (hcan->Instance == CAN3) + { + /* CAN3 is single instance with 14 dedicated filters banks */ + + /* Check the parameters */ + assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank)); + } + else + { + /* CAN1 and CAN2 are dual instances with 28 common filters banks */ + /* Select master instance to access the filter banks */ + can_ip = CAN1; + + /* Check the parameters */ + assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank)); + assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank)); + } +#elif defined(CAN2) + /* CAN1 and CAN2 are dual instances with 28 common filters banks */ + /* Select master instance to access the filter banks */ + can_ip = CAN1; + + /* Check the parameters */ + assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank)); + assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank)); +#else + /* CAN1 is single instance with 14 dedicated filters banks */ + + /* Check the parameters */ + assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank)); +#endif + + /* Initialisation mode for the filter */ + SET_BIT(can_ip->FMR, CAN_FMR_FINIT); + +#if defined(CAN3) + /* Check the CAN instance */ + if (can_ip == CAN1) + { + /* Select the start filter number of CAN2 slave instance */ + CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB); + SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos); + } + +#elif defined(CAN2) + /* Select the start filter number of CAN2 slave instance */ + CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB); + SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos); + +#endif + /* Convert filter number into bit position */ + filternbrbitpos = (uint32_t)1 << (sFilterConfig->FilterBank & 0x1FU); + + /* Filter Deactivation */ + CLEAR_BIT(can_ip->FA1R, filternbrbitpos); + + /* Filter Scale */ + if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT) + { + /* 16-bit scale for the filter */ + CLEAR_BIT(can_ip->FS1R, filternbrbitpos); + + /* First 16-bit identifier and First 16-bit mask */ + /* Or First 16-bit identifier and Second 16-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); + + /* Second 16-bit identifier and Second 16-bit mask */ + /* Or Third 16-bit identifier and Fourth 16-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh); + } + + if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT) + { + /* 32-bit scale for the filter */ + SET_BIT(can_ip->FS1R, filternbrbitpos); + + /* 32-bit identifier or First 32-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); + + /* 32-bit mask or Second 32-bit identifier */ + can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 = + ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | + (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow); + } + + /* Filter Mode */ + if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK) + { + /* Id/Mask mode for the filter*/ + CLEAR_BIT(can_ip->FM1R, filternbrbitpos); + } + else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */ + { + /* Identifier list mode for the filter*/ + SET_BIT(can_ip->FM1R, filternbrbitpos); + } + + /* Filter FIFO assignment */ + if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0) + { + /* FIFO 0 assignation for the filter */ + CLEAR_BIT(can_ip->FFA1R, filternbrbitpos); + } + else + { + /* FIFO 1 assignation for the filter */ + SET_BIT(can_ip->FFA1R, filternbrbitpos); + } + + /* Filter activation */ + if (sFilterConfig->FilterActivation == CAN_FILTER_ENABLE) + { + SET_BIT(can_ip->FA1R, filternbrbitpos); + } + + /* Leave the initialisation mode for the filter */ + CLEAR_BIT(can_ip->FMR, CAN_FMR_FINIT); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group3 Control functions + * @brief Control functions + * +@verbatim + ============================================================================== + ##### Control functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) HAL_CAN_Start : Start the CAN module + (+) HAL_CAN_Stop : Stop the CAN module + (+) HAL_CAN_RequestSleep : Request sleep mode entry. + (+) HAL_CAN_WakeUp : Wake up from sleep mode. + (+) HAL_CAN_IsSleepActive : Check is sleep mode is active. + (+) HAL_CAN_AddTxMessage : Add a message to the Tx mailboxes + and activate the corresponding + transmission request + (+) HAL_CAN_AbortTxRequest : Abort transmission request + (+) HAL_CAN_GetTxMailboxesFreeLevel : Return Tx mailboxes free level + (+) HAL_CAN_IsTxMessagePending : Check if a transmission request is + pending on the selected Tx mailbox + (+) HAL_CAN_GetRxMessage : Get a CAN frame from the Rx FIFO + (+) HAL_CAN_GetRxFifoFillLevel : Return Rx FIFO fill level + +@endverbatim + * @{ + */ + +/** + * @brief Start the CAN module. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan) +{ + uint32_t tickstart; + + if (hcan->State == HAL_CAN_STATE_READY) + { + /* Change CAN peripheral state */ + hcan->State = HAL_CAN_STATE_LISTENING; + + /* Request leave initialisation */ + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the acknowledge */ + while ((hcan->Instance->MSR & CAN_MSR_INAK) != 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Reset the CAN ErrorCode */ + hcan->ErrorCode = HAL_CAN_ERROR_NONE; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_READY; + + return HAL_ERROR; + } +} + +/** + * @brief Stop the CAN module and enable access to configuration registers. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan) +{ + uint32_t tickstart; + + if (hcan->State == HAL_CAN_STATE_LISTENING) + { + /* Request initialisation */ + SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the acknowledge */ + while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; + + /* Change CAN state */ + hcan->State = HAL_CAN_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Exit from sleep mode */ + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); + + /* Change CAN peripheral state */ + hcan->State = HAL_CAN_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_STARTED; + + return HAL_ERROR; + } +} + +/** + * @brief Request the sleep mode (low power) entry. + * When returning from this function, Sleep mode will be entered + * as soon as the current CAN activity (transmission or reception + * of a CAN frame) has been completed. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Request Sleep mode */ + SET_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Wake up from sleep mode. + * When returning with HAL_OK status from this function, Sleep mode + * is exited. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan) +{ + __IO uint32_t count = 0; + uint32_t timeout = 1000000U; + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Wake up request */ + CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); + + /* Wait sleep mode is exited */ + do + { + /* Increment counter */ + count++; + + /* Check if timeout is reached */ + if (count > timeout) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; + + return HAL_ERROR; + } + } + while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Check is sleep mode is active. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval Status + * - 0 : Sleep mode is not active. + * - 1 : Sleep mode is active. + */ +uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan) +{ + uint32_t status = 0U; + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check Sleep mode */ + if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) + { + status = 1U; + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Add a message to the first free Tx mailbox and activate the + * corresponding transmission request. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param pHeader pointer to a CAN_TxHeaderTypeDef structure. + * @param aData array containing the payload of the Tx frame. + * @param pTxMailbox pointer to a variable where the function will return + * the TxMailbox used to store the Tx message. + * This parameter can be a value of @arg CAN_Tx_Mailboxes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader, + const uint8_t aData[], uint32_t *pTxMailbox) +{ + uint32_t transmitmailbox; + HAL_CAN_StateTypeDef state = hcan->State; + uint32_t tsr = READ_REG(hcan->Instance->TSR); + + /* Check the parameters */ + assert_param(IS_CAN_IDTYPE(pHeader->IDE)); + assert_param(IS_CAN_RTR(pHeader->RTR)); + assert_param(IS_CAN_DLC(pHeader->DLC)); + if (pHeader->IDE == CAN_ID_STD) + { + assert_param(IS_CAN_STDID(pHeader->StdId)); + } + else + { + assert_param(IS_CAN_EXTID(pHeader->ExtId)); + } + assert_param(IS_FUNCTIONAL_STATE(pHeader->TransmitGlobalTime)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check that all the Tx mailboxes are not full */ + if (((tsr & CAN_TSR_TME0) != 0U) || + ((tsr & CAN_TSR_TME1) != 0U) || + ((tsr & CAN_TSR_TME2) != 0U)) + { + /* Select an empty transmit mailbox */ + transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos; + + /* Check transmit mailbox value */ + if (transmitmailbox > 2U) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_INTERNAL; + + return HAL_ERROR; + } + + /* Store the Tx mailbox */ + *pTxMailbox = (uint32_t)1 << transmitmailbox; + + /* Set up the Id */ + if (pHeader->IDE == CAN_ID_STD) + { + hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) | + pHeader->RTR); + } + else + { + hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) | + pHeader->IDE | + pHeader->RTR); + } + + /* Set up the DLC */ + hcan->Instance->sTxMailBox[transmitmailbox].TDTR = (pHeader->DLC); + + /* Set up the Transmit Global Time mode */ + if (pHeader->TransmitGlobalTime == ENABLE) + { + SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT); + } + + /* Set up the data field */ + WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, + ((uint32_t)aData[7] << CAN_TDH0R_DATA7_Pos) | + ((uint32_t)aData[6] << CAN_TDH0R_DATA6_Pos) | + ((uint32_t)aData[5] << CAN_TDH0R_DATA5_Pos) | + ((uint32_t)aData[4] << CAN_TDH0R_DATA4_Pos)); + WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, + ((uint32_t)aData[3] << CAN_TDL0R_DATA3_Pos) | + ((uint32_t)aData[2] << CAN_TDL0R_DATA2_Pos) | + ((uint32_t)aData[1] << CAN_TDL0R_DATA1_Pos) | + ((uint32_t)aData[0] << CAN_TDL0R_DATA0_Pos)); + + /* Request transmission */ + SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; + + return HAL_ERROR; + } + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Abort transmission requests + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param TxMailboxes List of the Tx Mailboxes to abort. + * This parameter can be any combination of @arg CAN_Tx_Mailboxes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check Tx Mailbox 0 */ + if ((TxMailboxes & CAN_TX_MAILBOX0) != 0U) + { + /* Add cancellation request for Tx Mailbox 0 */ + SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ0); + } + + /* Check Tx Mailbox 1 */ + if ((TxMailboxes & CAN_TX_MAILBOX1) != 0U) + { + /* Add cancellation request for Tx Mailbox 1 */ + SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ1); + } + + /* Check Tx Mailbox 2 */ + if ((TxMailboxes & CAN_TX_MAILBOX2) != 0U) + { + /* Add cancellation request for Tx Mailbox 2 */ + SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ2); + } + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Return Tx Mailboxes free level: number of free Tx Mailboxes. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval Number of free Tx Mailboxes. + */ +uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan) +{ + uint32_t freelevel = 0U; + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check Tx Mailbox 0 status */ + if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U) + { + freelevel++; + } + + /* Check Tx Mailbox 1 status */ + if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U) + { + freelevel++; + } + + /* Check Tx Mailbox 2 status */ + if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U) + { + freelevel++; + } + } + + /* Return Tx Mailboxes free level */ + return freelevel; +} + +/** + * @brief Check if a transmission request is pending on the selected Tx + * Mailboxes. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param TxMailboxes List of Tx Mailboxes to check. + * This parameter can be any combination of @arg CAN_Tx_Mailboxes. + * @retval Status + * - 0 : No pending transmission request on any selected Tx Mailboxes. + * - 1 : Pending transmission request on at least one of the selected + * Tx Mailbox. + */ +uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes) +{ + uint32_t status = 0U; + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check pending transmission request on the selected Tx Mailboxes */ + if ((hcan->Instance->TSR & (TxMailboxes << CAN_TSR_TME0_Pos)) != (TxMailboxes << CAN_TSR_TME0_Pos)) + { + status = 1U; + } + } + + /* Return status */ + return status; +} + +/** + * @brief Return timestamp of Tx message sent, if time triggered communication + mode is enabled. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param TxMailbox Tx Mailbox where the timestamp of message sent will be + * read. + * This parameter can be one value of @arg CAN_Tx_Mailboxes. + * @retval Timestamp of message sent from Tx Mailbox. + */ +uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox) +{ + uint32_t timestamp = 0U; + uint32_t transmitmailbox; + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_TX_MAILBOX(TxMailbox)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Select the Tx mailbox */ + transmitmailbox = POSITION_VAL(TxMailbox); + + /* Get timestamp */ + timestamp = (hcan->Instance->sTxMailBox[transmitmailbox].TDTR & CAN_TDT0R_TIME) >> CAN_TDT0R_TIME_Pos; + } + + /* Return the timestamp */ + return timestamp; +} + +/** + * @brief Get an CAN frame from the Rx FIFO zone into the message RAM. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param RxFifo Fifo number of the received message to be read. + * This parameter can be a value of @arg CAN_receive_FIFO_number. + * @param pHeader pointer to a CAN_RxHeaderTypeDef structure where the header + * of the Rx frame will be stored. + * @param aData array where the payload of the Rx frame will be stored. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, + CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + assert_param(IS_CAN_RX_FIFO(RxFifo)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check the Rx FIFO */ + if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */ + { + /* Check that the Rx FIFO 0 is not empty */ + if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) == 0U) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; + + return HAL_ERROR; + } + } + else /* Rx element is assigned to Rx FIFO 1 */ + { + /* Check that the Rx FIFO 1 is not empty */ + if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) == 0U) + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; + + return HAL_ERROR; + } + } + + /* Get the header */ + pHeader->IDE = CAN_RI0R_IDE & hcan->Instance->sFIFOMailBox[RxFifo].RIR; + if (pHeader->IDE == CAN_ID_STD) + { + pHeader->StdId = (CAN_RI0R_STID & hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_TI0R_STID_Pos; + } + else + { + pHeader->ExtId = ((CAN_RI0R_EXID | CAN_RI0R_STID) & + hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_RI0R_EXID_Pos; + } + pHeader->RTR = (CAN_RI0R_RTR & hcan->Instance->sFIFOMailBox[RxFifo].RIR); + pHeader->DLC = (CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos; + pHeader->FilterMatchIndex = (CAN_RDT0R_FMI & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_FMI_Pos; + pHeader->Timestamp = (CAN_RDT0R_TIME & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_TIME_Pos; + + /* Get the data */ + aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos); + aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos); + aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos); + aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos); + aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos); + aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos); + aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos); + aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos); + + /* Release the FIFO */ + if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */ + { + /* Release RX FIFO 0 */ + SET_BIT(hcan->Instance->RF0R, CAN_RF0R_RFOM0); + } + else /* Rx element is assigned to Rx FIFO 1 */ + { + /* Release RX FIFO 1 */ + SET_BIT(hcan->Instance->RF1R, CAN_RF1R_RFOM1); + } + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Return Rx FIFO fill level. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param RxFifo Rx FIFO. + * This parameter can be a value of @arg CAN_receive_FIFO_number. + * @retval Number of messages available in Rx FIFO. + */ +uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo) +{ + uint32_t filllevel = 0U; + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_RX_FIFO(RxFifo)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + if (RxFifo == CAN_RX_FIFO0) + { + filllevel = hcan->Instance->RF0R & CAN_RF0R_FMP0; + } + else /* RxFifo == CAN_RX_FIFO1 */ + { + filllevel = hcan->Instance->RF1R & CAN_RF1R_FMP1; + } + } + + /* Return Rx FIFO fill level */ + return filllevel; +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group4 Interrupts management + * @brief Interrupts management + * +@verbatim + ============================================================================== + ##### Interrupts management ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) HAL_CAN_ActivateNotification : Enable interrupts + (+) HAL_CAN_DeactivateNotification : Disable interrupts + (+) HAL_CAN_IRQHandler : Handles CAN interrupt request + +@endverbatim + * @{ + */ + +/** + * @brief Enable interrupts. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param ActiveITs indicates which interrupts will be enabled. + * This parameter can be any combination of @arg CAN_Interrupts. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_IT(ActiveITs)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Enable the selected interrupts */ + __HAL_CAN_ENABLE_IT(hcan, ActiveITs); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Disable interrupts. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @param InactiveITs indicates which interrupts will be disabled. + * This parameter can be any combination of @arg CAN_Interrupts. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + /* Check function parameters */ + assert_param(IS_CAN_IT(InactiveITs)); + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Disable the selected interrupts */ + __HAL_CAN_DISABLE_IT(hcan, InactiveITs); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + return HAL_ERROR; + } +} + +/** + * @brief Handles CAN interrupt request + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan) +{ + uint32_t errorcode = HAL_CAN_ERROR_NONE; + uint32_t interrupts = READ_REG(hcan->Instance->IER); + uint32_t msrflags = READ_REG(hcan->Instance->MSR); + uint32_t tsrflags = READ_REG(hcan->Instance->TSR); + uint32_t rf0rflags = READ_REG(hcan->Instance->RF0R); + uint32_t rf1rflags = READ_REG(hcan->Instance->RF1R); + uint32_t esrflags = READ_REG(hcan->Instance->ESR); + + /* Transmit Mailbox empty interrupt management *****************************/ + if ((interrupts & CAN_IT_TX_MAILBOX_EMPTY) != 0U) + { + /* Transmit Mailbox 0 management *****************************************/ + if ((tsrflags & CAN_TSR_RQCP0) != 0U) + { + /* Clear the Transmission Complete flag (and TXOK0,ALST0,TERR0 bits) */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP0); + + if ((tsrflags & CAN_TSR_TXOK0) != 0U) + { + /* Transmission Mailbox 0 complete callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox0CompleteCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox0CompleteCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + else + { + if ((tsrflags & CAN_TSR_ALST0) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_ALST0; + } + else if ((tsrflags & CAN_TSR_TERR0) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_TERR0; + } + else + { + /* Transmission Mailbox 0 abort callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox0AbortCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox0AbortCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + } + + /* Transmit Mailbox 1 management *****************************************/ + if ((tsrflags & CAN_TSR_RQCP1) != 0U) + { + /* Clear the Transmission Complete flag (and TXOK1,ALST1,TERR1 bits) */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP1); + + if ((tsrflags & CAN_TSR_TXOK1) != 0U) + { + /* Transmission Mailbox 1 complete callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox1CompleteCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox1CompleteCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + else + { + if ((tsrflags & CAN_TSR_ALST1) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_ALST1; + } + else if ((tsrflags & CAN_TSR_TERR1) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_TERR1; + } + else + { + /* Transmission Mailbox 1 abort callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox1AbortCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox1AbortCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + } + + /* Transmit Mailbox 2 management *****************************************/ + if ((tsrflags & CAN_TSR_RQCP2) != 0U) + { + /* Clear the Transmission Complete flag (and TXOK2,ALST2,TERR2 bits) */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP2); + + if ((tsrflags & CAN_TSR_TXOK2) != 0U) + { + /* Transmission Mailbox 2 complete callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox2CompleteCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox2CompleteCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + else + { + if ((tsrflags & CAN_TSR_ALST2) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_ALST2; + } + else if ((tsrflags & CAN_TSR_TERR2) != 0U) + { + /* Update error code */ + errorcode |= HAL_CAN_ERROR_TX_TERR2; + } + else + { + /* Transmission Mailbox 2 abort callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->TxMailbox2AbortCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_TxMailbox2AbortCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + } + } + + /* Receive FIFO 0 overrun interrupt management *****************************/ + if ((interrupts & CAN_IT_RX_FIFO0_OVERRUN) != 0U) + { + if ((rf0rflags & CAN_RF0R_FOVR0) != 0U) + { + /* Set CAN error code to Rx Fifo 0 overrun error */ + errorcode |= HAL_CAN_ERROR_RX_FOV0; + + /* Clear FIFO0 Overrun Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0); + } + } + + /* Receive FIFO 0 full interrupt management ********************************/ + if ((interrupts & CAN_IT_RX_FIFO0_FULL) != 0U) + { + if ((rf0rflags & CAN_RF0R_FULL0) != 0U) + { + /* Clear FIFO 0 full Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF0); + + /* Receive FIFO 0 full Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->RxFifo0FullCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_RxFifo0FullCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* Receive FIFO 0 message pending interrupt management *********************/ + if ((interrupts & CAN_IT_RX_FIFO0_MSG_PENDING) != 0U) + { + /* Check if message is still pending */ + if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) != 0U) + { + /* Receive FIFO 0 message pending Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->RxFifo0MsgPendingCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_RxFifo0MsgPendingCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* Receive FIFO 1 overrun interrupt management *****************************/ + if ((interrupts & CAN_IT_RX_FIFO1_OVERRUN) != 0U) + { + if ((rf1rflags & CAN_RF1R_FOVR1) != 0U) + { + /* Set CAN error code to Rx Fifo 1 overrun error */ + errorcode |= HAL_CAN_ERROR_RX_FOV1; + + /* Clear FIFO1 Overrun Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1); + } + } + + /* Receive FIFO 1 full interrupt management ********************************/ + if ((interrupts & CAN_IT_RX_FIFO1_FULL) != 0U) + { + if ((rf1rflags & CAN_RF1R_FULL1) != 0U) + { + /* Clear FIFO 1 full Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF1); + + /* Receive FIFO 1 full Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->RxFifo1FullCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_RxFifo1FullCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* Receive FIFO 1 message pending interrupt management *********************/ + if ((interrupts & CAN_IT_RX_FIFO1_MSG_PENDING) != 0U) + { + /* Check if message is still pending */ + if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) != 0U) + { + /* Receive FIFO 1 message pending Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->RxFifo1MsgPendingCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_RxFifo1MsgPendingCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* Sleep interrupt management *********************************************/ + if ((interrupts & CAN_IT_SLEEP_ACK) != 0U) + { + if ((msrflags & CAN_MSR_SLAKI) != 0U) + { + /* Clear Sleep interrupt Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_SLAKI); + + /* Sleep Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->SleepCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_SleepCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* WakeUp interrupt management *********************************************/ + if ((interrupts & CAN_IT_WAKEUP) != 0U) + { + if ((msrflags & CAN_MSR_WKUI) != 0U) + { + /* Clear WakeUp Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_WKU); + + /* WakeUp Callback */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->WakeUpFromRxMsgCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_WakeUpFromRxMsgCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } + } + + /* Error interrupts management *********************************************/ + if ((interrupts & CAN_IT_ERROR) != 0U) + { + if ((msrflags & CAN_MSR_ERRI) != 0U) + { + /* Check Error Warning Flag */ + if (((interrupts & CAN_IT_ERROR_WARNING) != 0U) && + ((esrflags & CAN_ESR_EWGF) != 0U)) + { + /* Set CAN error code to Error Warning */ + errorcode |= HAL_CAN_ERROR_EWG; + + /* No need for clear of Error Warning Flag as read-only */ + } + + /* Check Error Passive Flag */ + if (((interrupts & CAN_IT_ERROR_PASSIVE) != 0U) && + ((esrflags & CAN_ESR_EPVF) != 0U)) + { + /* Set CAN error code to Error Passive */ + errorcode |= HAL_CAN_ERROR_EPV; + + /* No need for clear of Error Passive Flag as read-only */ + } + + /* Check Bus-off Flag */ + if (((interrupts & CAN_IT_BUSOFF) != 0U) && + ((esrflags & CAN_ESR_BOFF) != 0U)) + { + /* Set CAN error code to Bus-Off */ + errorcode |= HAL_CAN_ERROR_BOF; + + /* No need for clear of Error Bus-Off as read-only */ + } + + /* Check Last Error Code Flag */ + if (((interrupts & CAN_IT_LAST_ERROR_CODE) != 0U) && + ((esrflags & CAN_ESR_LEC) != 0U)) + { + switch (esrflags & CAN_ESR_LEC) + { + case (CAN_ESR_LEC_0): + /* Set CAN error code to Stuff error */ + errorcode |= HAL_CAN_ERROR_STF; + break; + case (CAN_ESR_LEC_1): + /* Set CAN error code to Form error */ + errorcode |= HAL_CAN_ERROR_FOR; + break; + case (CAN_ESR_LEC_1 | CAN_ESR_LEC_0): + /* Set CAN error code to Acknowledgement error */ + errorcode |= HAL_CAN_ERROR_ACK; + break; + case (CAN_ESR_LEC_2): + /* Set CAN error code to Bit recessive error */ + errorcode |= HAL_CAN_ERROR_BR; + break; + case (CAN_ESR_LEC_2 | CAN_ESR_LEC_0): + /* Set CAN error code to Bit Dominant error */ + errorcode |= HAL_CAN_ERROR_BD; + break; + case (CAN_ESR_LEC_2 | CAN_ESR_LEC_1): + /* Set CAN error code to CRC error */ + errorcode |= HAL_CAN_ERROR_CRC; + break; + default: + break; + } + + /* Clear Last error code Flag */ + CLEAR_BIT(hcan->Instance->ESR, CAN_ESR_LEC); + } + } + + /* Clear ERRI Flag */ + __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_ERRI); + } + + /* Call the Error call Back in case of Errors */ + if (errorcode != HAL_CAN_ERROR_NONE) + { + /* Update error code in handle */ + hcan->ErrorCode |= errorcode; + + /* Call Error callback function */ +#if USE_HAL_CAN_REGISTER_CALLBACKS == 1 + /* Call registered callback*/ + hcan->ErrorCallback(hcan); +#else + /* Call weak (surcharged) callback */ + HAL_CAN_ErrorCallback(hcan); +#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ + } +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group5 Callback functions + * @brief CAN Callback functions + * +@verbatim + ============================================================================== + ##### Callback functions ##### + ============================================================================== + [..] + This subsection provides the following callback functions: + (+) HAL_CAN_TxMailbox0CompleteCallback + (+) HAL_CAN_TxMailbox1CompleteCallback + (+) HAL_CAN_TxMailbox2CompleteCallback + (+) HAL_CAN_TxMailbox0AbortCallback + (+) HAL_CAN_TxMailbox1AbortCallback + (+) HAL_CAN_TxMailbox2AbortCallback + (+) HAL_CAN_RxFifo0MsgPendingCallback + (+) HAL_CAN_RxFifo0FullCallback + (+) HAL_CAN_RxFifo1MsgPendingCallback + (+) HAL_CAN_RxFifo1FullCallback + (+) HAL_CAN_SleepCallback + (+) HAL_CAN_WakeUpFromRxMsgCallback + (+) HAL_CAN_ErrorCallback + +@endverbatim + * @{ + */ + +/** + * @brief Transmission Mailbox 0 complete callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox0CompleteCallback could be implemented in the + user file + */ +} + +/** + * @brief Transmission Mailbox 1 complete callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox1CompleteCallback could be implemented in the + user file + */ +} + +/** + * @brief Transmission Mailbox 2 complete callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox2CompleteCallback could be implemented in the + user file + */ +} + +/** + * @brief Transmission Mailbox 0 Cancellation callback. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox0AbortCallback could be implemented in the + user file + */ +} + +/** + * @brief Transmission Mailbox 1 Cancellation callback. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox1AbortCallback could be implemented in the + user file + */ +} + +/** + * @brief Transmission Mailbox 2 Cancellation callback. + * @param hcan pointer to an CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_TxMailbox2AbortCallback could be implemented in the + user file + */ +} + +/** + * @brief Rx FIFO 0 message pending callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxFifo0MsgPendingCallback could be implemented in the + user file + */ +} + +/** + * @brief Rx FIFO 0 full callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxFifo0FullCallback could be implemented in the user + file + */ +} + +/** + * @brief Rx FIFO 1 message pending callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxFifo1MsgPendingCallback could be implemented in the + user file + */ +} + +/** + * @brief Rx FIFO 1 full callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_RxFifo1FullCallback could be implemented in the user + file + */ +} + +/** + * @brief Sleep callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_SleepCallback could be implemented in the user file + */ +} + +/** + * @brief WakeUp from Rx message callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_WakeUpFromRxMsgCallback could be implemented in the + user file + */ +} + +/** + * @brief Error CAN callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +__weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcan); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CAN_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup CAN_Exported_Functions_Group6 Peripheral State and Error functions + * @brief CAN Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] + This subsection provides functions allowing to : + (+) HAL_CAN_GetState() : Return the CAN state. + (+) HAL_CAN_GetError() : Return the CAN error codes if any. + (+) HAL_CAN_ResetError(): Reset the CAN error codes if any. + +@endverbatim + * @{ + */ + +/** + * @brief Return the CAN state. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL state + */ +HAL_CAN_StateTypeDef HAL_CAN_GetState(const CAN_HandleTypeDef *hcan) +{ + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Check sleep mode acknowledge flag */ + if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) + { + /* Sleep mode is active */ + state = HAL_CAN_STATE_SLEEP_ACTIVE; + } + /* Check sleep mode request flag */ + else if ((hcan->Instance->MCR & CAN_MCR_SLEEP) != 0U) + { + /* Sleep mode request is pending */ + state = HAL_CAN_STATE_SLEEP_PENDING; + } + else + { + /* Neither sleep mode request nor sleep mode acknowledge */ + } + } + + /* Return CAN state */ + return state; +} + +/** + * @brief Return the CAN error code. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval CAN Error Code + */ +uint32_t HAL_CAN_GetError(const CAN_HandleTypeDef *hcan) +{ + /* Return CAN error code */ + return hcan->ErrorCode; +} + +/** + * @brief Reset the CAN error code. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_CAN_StateTypeDef state = hcan->State; + + if ((state == HAL_CAN_STATE_READY) || + (state == HAL_CAN_STATE_LISTENING)) + { + /* Reset CAN error code */ + hcan->ErrorCode = 0U; + } + else + { + /* Update error code */ + hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; + + status = HAL_ERROR; + } + + /* Return the status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_CAN_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* CAN1 */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c new file mode 100644 index 0000000..3ef9e3f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cec.c @@ -0,0 +1,996 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cec.c + * @author MCD Application Team + * @brief CEC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the High Definition Multimedia Interface + * Consumer Electronics Control Peripheral (CEC). + * + Initialization and de-initialization function + * + IO operation function + * + Peripheral Control function + * + * + ****************************************************************************** + * @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 CEC HAL driver can be used as follow: + + (#) Declare a CEC_HandleTypeDef handle structure. + (#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API: + (##) Enable the CEC interface clock. + (##) CEC pins configuration: + (+++) Enable the clock for the CEC GPIOs. + (+++) Configure these CEC pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT() + and HAL_CEC_Receive_IT() APIs): + (+++) Configure the CEC interrupt priority. + (+++) Enable the NVIC CEC IRQ handle. + (+++) The specific CEC interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit + and receive process. + + (#) Program the Signal Free Time (SFT) and SFT option, Tolerance, reception stop in + in case of Bit Rising Error, Error-Bit generation conditions, device logical + address and Listen mode in the hcec Init structure. + + (#) Initialize the CEC registers by calling the HAL_CEC_Init() API. + + [..] + (@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc) + by calling the customed HAL_CEC_MspInit() API. + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_CEC_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback() + to register an interrupt callback. + + Function HAL_CEC_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Transfer completed callback. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : CEC MspInit. + (+) MspDeInitCallback : CEC MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks + HAL_CEC_RegisterRxCpltCallback(). + + Use function HAL_CEC_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Transfer completed callback. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : CEC MspInit. + (+) MspDeInitCallback : CEC MspDeInit. + + For callback HAL_CEC_RxCpltCallback use dedicated unregister callback : + HAL_CEC_UnRegisterRxCpltCallback(). + + By default, after the HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET + all callbacks are set to the corresponding weak functions : + examples HAL_CEC_TxCpltCallback() , HAL_CEC_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_CEC_Init()/ HAL_CEC_DeInit() only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_CEC_Init() / HAL_CEC_DeInit() + keep and use the user MspInit/MspDeInit functions (registered beforehand) + + Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only. + Exception done MspInit/MspDeInit callbacks that can be registered/unregistered + in HAL_CEC_STATE_READY or HAL_CEC_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_CEC_RegisterCallback() before calling HAL_CEC_DeInit() + or HAL_CEC_Init() function. + + When the compilation define USE_HAL_CEC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup CEC CEC + * @brief HAL CEC module driver + * @{ + */ +#ifdef HAL_CEC_MODULE_ENABLED +#if defined (CEC) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup CEC_Private_Constants CEC Private Constants + * @{ + */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup CEC_Private_Functions CEC Private Functions + * @{ + */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup CEC_Exported_Functions CEC Exported Functions + * @{ + */ + +/** @defgroup CEC_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 CEC + (+) The following parameters need to be configured: + (++) SignalFreeTime + (++) Tolerance + (++) BRERxStop (RX stopped or not upon Bit Rising Error) + (++) BREErrorBitGen (Error-Bit generation in case of Bit Rising Error) + (++) LBPEErrorBitGen (Error-Bit generation in case of Long Bit Period Error) + (++) BroadcastMsgNoErrorBitGen (Error-bit generation in case of broadcast message error) + (++) SignalFreeTimeOption (SFT Timer start definition) + (++) OwnAddress (CEC device address) + (++) ListenMode + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the CEC mode according to the specified + * parameters in the CEC_InitTypeDef and creates the associated handle . + * @param hcec CEC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec) +{ + /* Check the CEC handle allocation */ + if ((hcec == NULL) || (hcec->Init.RxBuffer == NULL)) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance)); + assert_param(IS_CEC_SIGNALFREETIME(hcec->Init.SignalFreeTime)); + assert_param(IS_CEC_TOLERANCE(hcec->Init.Tolerance)); + assert_param(IS_CEC_BRERXSTOP(hcec->Init.BRERxStop)); + assert_param(IS_CEC_BREERRORBITGEN(hcec->Init.BREErrorBitGen)); + assert_param(IS_CEC_LBPEERRORBITGEN(hcec->Init.LBPEErrorBitGen)); + assert_param(IS_CEC_BROADCASTERROR_NO_ERRORBIT_GENERATION(hcec->Init.BroadcastMsgNoErrorBitGen)); + assert_param(IS_CEC_SFTOP(hcec->Init.SignalFreeTimeOption)); + assert_param(IS_CEC_LISTENING_MODE(hcec->Init.ListenMode)); + assert_param(IS_CEC_OWN_ADDRESS(hcec->Init.OwnAddress)); + +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) + if (hcec->gState == HAL_CEC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcec->Lock = HAL_UNLOCKED; + + hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hcec->MspInitCallback == NULL) + { + hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware */ + hcec->MspInitCallback(hcec); + } +#else + if (hcec->gState == HAL_CEC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcec->Lock = HAL_UNLOCKED; + /* Init the low level hardware : GPIO, CLOCK */ + HAL_CEC_MspInit(hcec); + } +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + + hcec->gState = HAL_CEC_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_CEC_DISABLE(hcec); + + /* Write to CEC Control Register */ + hcec->Instance->CFGR = hcec->Init.SignalFreeTime | hcec->Init.Tolerance | hcec->Init.BRERxStop | \ + hcec->Init.BREErrorBitGen | hcec->Init.LBPEErrorBitGen | hcec->Init.BroadcastMsgNoErrorBitGen | \ + hcec->Init.SignalFreeTimeOption | ((uint32_t)(hcec->Init.OwnAddress) << 16U) | \ + hcec->Init.ListenMode; + + /* Enable the following CEC Transmission/Reception interrupts as + * well as the following CEC Transmission/Reception Errors interrupts + * Rx Byte Received IT + * End of Reception IT + * Rx overrun + * Rx bit rising error + * Rx short bit period error + * Rx long bit period error + * Rx missing acknowledge + * Tx Byte Request IT + * End of Transmission IT + * Tx Missing Acknowledge IT + * Tx-Error IT + * Tx-Buffer Underrun IT + * Tx arbitration lost */ + __HAL_CEC_ENABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND | + CEC_IER_TX_ALL_ERR); + + /* Enable the CEC Peripheral */ + __HAL_CEC_ENABLE(hcec); + + hcec->ErrorCode = HAL_CEC_ERROR_NONE; + hcec->gState = HAL_CEC_STATE_READY; + hcec->RxState = HAL_CEC_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the CEC peripheral + * @param hcec CEC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec) +{ + /* Check the CEC handle allocation */ + if (hcec == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance)); + + hcec->gState = HAL_CEC_STATE_BUSY; + +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) + if (hcec->MspDeInitCallback == NULL) + { + hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware */ + hcec->MspDeInitCallback(hcec); + +#else + /* DeInit the low level hardware */ + HAL_CEC_MspDeInit(hcec); +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + + /* Disable the Peripheral */ + __HAL_CEC_DISABLE(hcec); + + /* Clear Flags */ + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND | CEC_FLAG_TXBR | CEC_FLAG_RXBR | CEC_FLAG_RXEND | CEC_ISR_ALL_ERROR); + + /* Disable the following CEC Transmission/Reception interrupts as + * well as the following CEC Transmission/Reception Errors interrupts + * Rx Byte Received IT + * End of Reception IT + * Rx overrun + * Rx bit rising error + * Rx short bit period error + * Rx long bit period error + * Rx missing acknowledge + * Tx Byte Request IT + * End of Transmission IT + * Tx Missing Acknowledge IT + * Tx-Error IT + * Tx-Buffer Underrun IT + * Tx arbitration lost */ + __HAL_CEC_DISABLE_IT(hcec, CEC_IT_RXBR | CEC_IT_RXEND | CEC_IER_RX_ALL_ERR | CEC_IT_TXBR | CEC_IT_TXEND | + CEC_IER_TX_ALL_ERR); + + hcec->ErrorCode = HAL_CEC_ERROR_NONE; + hcec->gState = HAL_CEC_STATE_RESET; + hcec->RxState = HAL_CEC_STATE_RESET; + + /* Process Unlock */ + __HAL_UNLOCK(hcec); + + return HAL_OK; +} + +/** + * @brief Initializes the Own Address of the CEC device + * @param hcec CEC handle + * @param CEC_OwnAddress The CEC own address. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress) +{ + /* Check the parameters */ + assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress)); + + if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY)) + { + /* Process Locked */ + __HAL_LOCK(hcec); + + hcec->gState = HAL_CEC_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_CEC_DISABLE(hcec); + + if (CEC_OwnAddress != CEC_OWN_ADDRESS_NONE) + { + hcec->Instance->CFGR |= ((uint32_t)CEC_OwnAddress << 16); + } + else + { + hcec->Instance->CFGR &= ~(CEC_CFGR_OAR); + } + + hcec->gState = HAL_CEC_STATE_READY; + hcec->ErrorCode = HAL_CEC_ERROR_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hcec); + + /* Enable the Peripheral */ + __HAL_CEC_ENABLE(hcec); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief CEC MSP Init + * @param hcec CEC handle + * @retval None + */ +__weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcec); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CEC_MspInit can be implemented in the user file + */ +} + +/** + * @brief CEC MSP DeInit + * @param hcec CEC handle + * @retval None + */ +__weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcec); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CEC_MspDeInit can be implemented in the user file + */ +} +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User CEC Callback + * To be used instead of the weak predefined callback + * @param hcec CEC handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID + * @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID, + pCEC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hcec); + + if (hcec->gState == HAL_CEC_STATE_READY) + { + switch (CallbackID) + { + case HAL_CEC_TX_CPLT_CB_ID : + hcec->TxCpltCallback = pCallback; + break; + + case HAL_CEC_ERROR_CB_ID : + hcec->ErrorCallback = pCallback; + break; + + case HAL_CEC_MSPINIT_CB_ID : + hcec->MspInitCallback = pCallback; + break; + + case HAL_CEC_MSPDEINIT_CB_ID : + hcec->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcec->gState == HAL_CEC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CEC_MSPINIT_CB_ID : + hcec->MspInitCallback = pCallback; + break; + + case HAL_CEC_MSPDEINIT_CB_ID : + hcec->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcec); + + return status; +} + +/** + * @brief Unregister an CEC Callback + * CEC callback is redirected to the weak predefined callback + * @param hcec uart handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID + * @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hcec); + + if (hcec->gState == HAL_CEC_STATE_READY) + { + switch (CallbackID) + { + case HAL_CEC_TX_CPLT_CB_ID : + hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_CEC_ERROR_CB_ID : + hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_CEC_MSPINIT_CB_ID : + hcec->MspInitCallback = HAL_CEC_MspInit; + break; + + case HAL_CEC_MSPDEINIT_CB_ID : + hcec->MspDeInitCallback = HAL_CEC_MspDeInit; + break; + + default : + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcec->gState == HAL_CEC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CEC_MSPINIT_CB_ID : + hcec->MspInitCallback = HAL_CEC_MspInit; + break; + + case HAL_CEC_MSPDEINIT_CB_ID : + hcec->MspDeInitCallback = HAL_CEC_MspDeInit; + break; + + default : + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcec); + + return status; +} + +/** + * @brief Register CEC RX complete Callback + * To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback + * @param hcec CEC handle + * @param pCallback pointer to the Rx transfer compelete Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hcec); + + if (HAL_CEC_STATE_READY == hcec->RxState) + { + hcec->RxCpltCallback = pCallback; + } + else + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcec); + return status; +} + +/** + * @brief UnRegister CEC RX complete Callback + * CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback + * @param hcec CEC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hcec); + + if (HAL_CEC_STATE_READY == hcec->RxState) + { + hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak CEC RxCpltCallback */ + } + else + { + /* Update the error code */ + hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcec); + return status; +} +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions + * @brief CEC Transmit/Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + This subsection provides a set of functions allowing to manage the CEC data transfers. + + (#) The CEC handle must contain the initiator (TX side) and the destination (RX side) + logical addresses (4-bit long addresses, 0xF for broadcast messages destination) + + (#) The communication is performed using Interrupts. + These API's return the HAL status. + The end of the data processing will be indicated through the + dedicated CEC IRQ when using Interrupt mode. + The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_CEC_ErrorCallback() user callback will be executed when a communication + error is detected + + (#) API's with Interrupt are : + (+) HAL_CEC_Transmit_IT() + (+) HAL_CEC_IRQHandler() + + (#) A set of User Callbacks are provided: + (+) HAL_CEC_TxCpltCallback() + (+) HAL_CEC_RxCpltCallback() + (+) HAL_CEC_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Send data in interrupt mode + * @param hcec CEC handle + * @param InitiatorAddress Initiator address + * @param DestinationAddress destination logical address + * @param pData pointer to input byte data buffer + * @param Size amount of data to be sent in bytes (without counting the header). + * 0 means only the header is sent (ping operation). + * Maximum TX size is 15 bytes (1 opcode and up to 14 operands). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress, + const uint8_t *pData, uint32_t Size) +{ + /* if the peripheral isn't already busy and if there is no previous transmission + already pending due to arbitration lost */ + if (hcec->gState == HAL_CEC_STATE_READY) + { + if ((pData == NULL) && (Size > 0U)) + { + return HAL_ERROR; + } + + assert_param(IS_CEC_ADDRESS(DestinationAddress)); + assert_param(IS_CEC_ADDRESS(InitiatorAddress)); + assert_param(IS_CEC_MSGSIZE(Size)); + + /* Process Locked */ + __HAL_LOCK(hcec); + hcec->pTxBuffPtr = pData; + hcec->gState = HAL_CEC_STATE_BUSY_TX; + hcec->ErrorCode = HAL_CEC_ERROR_NONE; + + /* initialize the number of bytes to send, + * 0 means only one header is sent (ping operation) */ + hcec->TxXferCount = (uint16_t)Size; + + /* in case of no payload (Size = 0), sender is only pinging the system; + Set TX End of Message (TXEOM) bit, must be set before writing data to TXDR */ + if (Size == 0U) + { + __HAL_CEC_LAST_BYTE_TX_SET(hcec); + } + + /* send header block */ + hcec->Instance->TXDR = (uint32_t)(((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress); + + /* Set TX Start of Message (TXSOM) bit */ + __HAL_CEC_FIRST_BYTE_TX_SET(hcec); + + /* Process Unlocked */ + __HAL_UNLOCK(hcec); + + return HAL_OK; + + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Get size of the received frame. + * @param hcec CEC handle + * @retval Frame size + */ +uint32_t HAL_CEC_GetLastReceivedFrameSize(const CEC_HandleTypeDef *hcec) +{ + return hcec->RxXferSize; +} + +/** + * @brief Change Rx Buffer. + * @param hcec CEC handle + * @param Rxbuffer Rx Buffer + * @note This function can be called only inside the HAL_CEC_RxCpltCallback() + * @retval Frame size + */ +void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer) +{ + hcec->Init.RxBuffer = Rxbuffer; +} + +/** + * @brief This function handles CEC interrupt requests. + * @param hcec CEC handle + * @retval None + */ +void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec) +{ + + /* save interrupts register for further error or interrupts handling purposes */ + uint32_t itflag; + itflag = hcec->Instance->ISR; + + + /* ----------------------------Arbitration Lost Management----------------------------------*/ + /* CEC TX arbitration error interrupt occurred --------------------------------------*/ + if (HAL_IS_BIT_SET(itflag, CEC_FLAG_ARBLST)) + { + hcec->ErrorCode = HAL_CEC_ERROR_ARBLST; + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_ARBLST); + } + + /* ----------------------------Rx Management----------------------------------*/ + /* CEC RX byte received interrupt ---------------------------------------------------*/ + if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RXBR)) + { + /* reception is starting */ + hcec->RxState = HAL_CEC_STATE_BUSY_RX; + hcec->RxXferSize++; + /* read received byte */ + *hcec->Init.RxBuffer = (uint8_t) hcec->Instance->RXDR; + hcec->Init.RxBuffer++; + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXBR); + } + + /* CEC RX end received interrupt ---------------------------------------------------*/ + if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RXEND)) + { + /* clear IT */ + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RXEND); + + /* Rx process is completed, restore hcec->RxState to Ready */ + hcec->RxState = HAL_CEC_STATE_READY; + hcec->ErrorCode = HAL_CEC_ERROR_NONE; + hcec->Init.RxBuffer -= hcec->RxXferSize; +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U) + hcec->RxCpltCallback(hcec, hcec->RxXferSize); +#else + HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize); +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + hcec->RxXferSize = 0U; + } + + /* ----------------------------Tx Management----------------------------------*/ + /* CEC TX byte request interrupt ------------------------------------------------*/ + if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TXBR)) + { + --hcec->TxXferCount; + if (hcec->TxXferCount == 0U) + { + /* if this is the last byte transmission, set TX End of Message (TXEOM) bit */ + __HAL_CEC_LAST_BYTE_TX_SET(hcec); + } + /* In all cases transmit the byte */ + hcec->Instance->TXDR = (uint8_t)*hcec->pTxBuffPtr; + hcec->pTxBuffPtr++; + /* clear Tx-Byte request flag */ + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXBR); + } + + /* CEC TX end interrupt ------------------------------------------------*/ + if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TXEND)) + { + __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TXEND); + + /* Tx process is ended, restore hcec->gState to Ready */ + hcec->gState = HAL_CEC_STATE_READY; + /* Call the Process Unlocked before calling the Tx call back API to give the possibility to + start again the Transmission under the Tx call back API */ + __HAL_UNLOCK(hcec); + hcec->ErrorCode = HAL_CEC_ERROR_NONE; +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U) + hcec->TxCpltCallback(hcec); +#else + HAL_CEC_TxCpltCallback(hcec); +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + } + + /* ----------------------------Rx/Tx Error Management----------------------------------*/ + if ((itflag & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE | CEC_ISR_TXUDR | + CEC_ISR_TXERR | CEC_ISR_TXACKE)) != 0U) + { + hcec->ErrorCode = itflag; + __HAL_CEC_CLEAR_FLAG(hcec, HAL_CEC_ERROR_RXOVR | HAL_CEC_ERROR_BRE | CEC_FLAG_LBPE | CEC_FLAG_SBPE | + HAL_CEC_ERROR_RXACKE | HAL_CEC_ERROR_TXUDR | HAL_CEC_ERROR_TXERR | HAL_CEC_ERROR_TXACKE); + + + if ((itflag & (CEC_ISR_RXOVR | CEC_ISR_BRE | CEC_ISR_SBPE | CEC_ISR_LBPE | CEC_ISR_RXACKE)) != 0U) + { + hcec->Init.RxBuffer -= hcec->RxXferSize; + hcec->RxXferSize = 0U; + hcec->RxState = HAL_CEC_STATE_READY; + } + else if (((itflag & CEC_ISR_ARBLST) == 0U) && ((itflag & (CEC_ISR_TXUDR | CEC_ISR_TXERR | CEC_ISR_TXACKE)) != 0U)) + { + /* Set the CEC state ready to be able to start again the process */ + hcec->gState = HAL_CEC_STATE_READY; + } + else + { + /* Nothing todo*/ + } +#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1U) + hcec->ErrorCallback(hcec); +#else + /* Error Call Back */ + HAL_CEC_ErrorCallback(hcec); +#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */ + } + else + { + /* Nothing todo*/ + } +} + +/** + * @brief Tx Transfer completed callback + * @param hcec CEC handle + * @retval None + */ +__weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcec); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CEC_TxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback + * @param hcec CEC handle + * @param RxFrameSize Size of frame + * @retval None + */ +__weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcec); + UNUSED(RxFrameSize); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CEC_RxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief CEC error callbacks + * @param hcec CEC handle + * @retval None + */ +__weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcec); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CEC_ErrorCallback can be implemented in the user file + */ +} +/** + * @} + */ + +/** @defgroup CEC_Exported_Functions_Group3 Peripheral Control function + * @brief CEC control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control function ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the CEC. + (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral. + (+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral. +@endverbatim + * @{ + */ +/** + * @brief return the CEC state + * @param hcec pointer to a CEC_HandleTypeDef structure that contains + * the configuration information for the specified CEC module. + * @retval HAL state + */ +HAL_CEC_StateTypeDef HAL_CEC_GetState(const CEC_HandleTypeDef *hcec) +{ + uint32_t temp1, temp2; + temp1 = hcec->gState; + temp2 = hcec->RxState; + + return (HAL_CEC_StateTypeDef)(temp1 | temp2); +} + +/** + * @brief Return the CEC error code + * @param hcec pointer to a CEC_HandleTypeDef structure that contains + * the configuration information for the specified CEC. + * @retval CEC Error Code + */ +uint32_t HAL_CEC_GetError(const CEC_HandleTypeDef *hcec) +{ + return hcec->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ +#endif /* CEC */ +#endif /* HAL_CEC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/hal/stm32f4xx_hal_cortex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_cortex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cortex.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c new file mode 100644 index 0000000..2e86b2b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_crc.c @@ -0,0 +1,328 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_crc.c + * @author MCD Application Team + * @brief CRC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Cyclic Redundancy Check (CRC) peripheral: + * + Initialization and de-initialization functions + * + Peripheral Control functions + * + Peripheral State 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 ##### + =============================================================================== + [..] + (+) Enable CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE(); + (+) Initialize CRC calculator + (++) specify generating polynomial (peripheral default or non-default one) + (++) specify initialization value (peripheral default or non-default one) + (++) specify input data format + (++) specify input or output data inversion mode if any + (+) Use HAL_CRC_Accumulate() function to compute the CRC value of the + input data buffer starting with the previously computed CRC as + initialization value + (+) Use HAL_CRC_Calculate() function to compute the CRC value of the + input data buffer starting with the defined initialization value + (default or non-default) to initiate CRC calculation + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup CRC CRC + * @brief CRC HAL module driver. + * @{ + */ + +#ifdef HAL_CRC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup CRC_Exported_Functions CRC Exported Functions + * @{ + */ + +/** @defgroup CRC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions. + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the CRC according to the specified parameters + in the CRC_InitTypeDef and create the associated handle + (+) DeInitialize the CRC peripheral + (+) Initialize the CRC MSP (MCU Specific Package) + (+) DeInitialize the CRC MSP + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the CRC according to the specified + * parameters in the CRC_InitTypeDef and create the associated handle. + * @param hcrc CRC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc) +{ + /* Check the CRC handle allocation */ + if (hcrc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance)); + + if (hcrc->State == HAL_CRC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcrc->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_CRC_MspInit(hcrc); + } + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief DeInitialize the CRC peripheral. + * @param hcrc CRC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc) +{ + /* Check the CRC handle allocation */ + if (hcrc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance)); + + /* Check the CRC peripheral state */ + if (hcrc->State == HAL_CRC_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_BUSY; + + /* Reset CRC calculation unit */ + __HAL_CRC_DR_RESET(hcrc); + + /* Reset IDR register content */ + CLEAR_BIT(hcrc->Instance->IDR, CRC_IDR_IDR); + + /* DeInit the low level hardware */ + HAL_CRC_MspDeInit(hcrc); + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_RESET; + + /* Process unlocked */ + __HAL_UNLOCK(hcrc); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the CRC MSP. + * @param hcrc CRC handle + * @retval None + */ +__weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcrc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRC_MspInit can be implemented in the user file + */ +} + +/** + * @brief DeInitialize the CRC MSP. + * @param hcrc CRC handle + * @retval None + */ +__weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcrc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRC_MspDeInit can be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions + * @brief management functions. + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) compute the 32-bit CRC value of a 32-bit data buffer + using combination of the previous CRC value and the new one. + + [..] or + + (+) compute the 32-bit CRC value of a 32-bit data buffer + independently of the previous CRC value. + +@endverbatim + * @{ + */ + +/** + * @brief Compute the 32-bit CRC value of a 32-bit data buffer + * starting with the previously computed CRC as initialization value. + * @param hcrc CRC handle + * @param pBuffer pointer to the input data buffer. + * @param BufferLength input data buffer length (number of uint32_t words). + * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits) + */ +uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index; /* CRC input data buffer index */ + uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */ + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_BUSY; + + /* Enter Data to the CRC calculator */ + for (index = 0U; index < BufferLength; index++) + { + hcrc->Instance->DR = pBuffer[index]; + } + temp = hcrc->Instance->DR; + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_READY; + + /* Return the CRC computed value */ + return temp; +} + +/** + * @brief Compute the 32-bit CRC value of a 32-bit data buffer + * starting with hcrc->Instance->INIT as initialization value. + * @param hcrc CRC handle + * @param pBuffer pointer to the input data buffer. + * @param BufferLength input data buffer length (number of uint32_t words). + * @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits) + */ +uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index; /* CRC input data buffer index */ + uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */ + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_BUSY; + + /* Reset CRC Calculation Unit (hcrc->Instance->INIT is + * written in hcrc->Instance->DR) */ + __HAL_CRC_DR_RESET(hcrc); + + /* Enter 32-bit input data to the CRC calculator */ + for (index = 0U; index < BufferLength; index++) + { + hcrc->Instance->DR = pBuffer[index]; + } + temp = hcrc->Instance->DR; + + /* Change CRC peripheral state */ + hcrc->State = HAL_CRC_STATE_READY; + + /* Return the CRC computed value */ + return temp; +} + +/** + * @} + */ + +/** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions + * @brief Peripheral State functions. + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Return the CRC handle state. + * @param hcrc CRC handle + * @retval HAL state + */ +HAL_CRC_StateTypeDef HAL_CRC_GetState(CRC_HandleTypeDef *hcrc) +{ + /* Return CRC handle state */ + return hcrc->State; +} + +/** + * @} + */ + +/** + * @} + */ + + +#endif /* HAL_CRC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c new file mode 100644 index 0000000..c439c2c --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp.c @@ -0,0 +1,7158 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cryp.c + * @author MCD Application Team + * @brief CRYP HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Cryptography (CRYP) peripheral: + * + Initialization, de-initialization, set config and get config functions + * + DES/TDES, AES processing functions + * + DMA callback functions + * + CRYP IRQ handler management + * + Peripheral State 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 CRYP HAL driver can be used in CRYP or TinyAES IP as follows: + + (#)Initialize the CRYP low level resources by implementing the HAL_CRYP_MspInit(): + (##) Enable the CRYP interface clock using __HAL_RCC_CRYP_CLK_ENABLE()or __HAL_RCC_AES_CLK_ENABLE for TinyAES IP + (##) In case of using interrupts (e.g. HAL_CRYP_Encrypt_IT()) + (+++) Configure the CRYP interrupt priority using HAL_NVIC_SetPriority() + (+++) Enable the CRYP IRQ handler using HAL_NVIC_EnableIRQ() + (+++) In CRYP IRQ handler, call HAL_CRYP_IRQHandler() + (##) In case of using DMA to control data transfer (e.g. HAL_CRYP_Encrypt_DMA()) + (+++) Enable the DMAx interface clock using __RCC_DMAx_CLK_ENABLE() + (+++) Configure and enable two DMA streams one for managing data transfer from + memory to peripheral (input stream) and another stream for managing data + transfer from peripheral to memory (output stream) + (+++) Associate the initialized DMA handle to the CRYP DMA handle + using __HAL_LINKDMA() + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the two DMA Streams. The output stream should have higher + priority than the input stream HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ() + + (#)Initialize the CRYP according to the specified parameters : + (##) The data type: 1-bit, 8-bit, 16-bit or 32-bit. + (##) The key size: 128, 192 or 256. + (##) The AlgoMode DES/ TDES Algorithm ECB/CBC or AES Algorithm ECB/CBC/CTR/GCM or CCM. + (##) The initialization vector (counter). It is not used in ECB mode. + (##) The key buffer used for encryption/decryption. + (##) The Header used only in AES GCM and CCM Algorithm for authentication. + (##) The HeaderSize The size of header buffer in word. + (##) The B0 block is the first authentication block used only in AES CCM mode. + + (#)Three processing (encryption/decryption) functions are available: + (##) Polling mode: encryption and decryption APIs are blocking functions + i.e. they process the data and wait till the processing is finished, + e.g. HAL_CRYP_Encrypt & HAL_CRYP_Decrypt + (##) Interrupt mode: encryption and decryption APIs are not blocking functions + i.e. they process the data under interrupt, + e.g. HAL_CRYP_Encrypt_IT & HAL_CRYP_Decrypt_IT + (##) DMA mode: encryption and decryption APIs are not blocking functions + i.e. the data transfer is ensured by DMA, + e.g. HAL_CRYP_Encrypt_DMA & HAL_CRYP_Decrypt_DMA + + (#)When the processing function is called at first time after HAL_CRYP_Init() + the CRYP peripheral is configured and processes the buffer in input. + At second call, no need to Initialize the CRYP, user have to get current configuration via + HAL_CRYP_GetConfig() API, then only HAL_CRYP_SetConfig() is requested to set + new parametres, finally user can start encryption/decryption. + + (#)Call HAL_CRYP_DeInit() to deinitialize the CRYP peripheral. + + (#)To process a single message with consecutive calls to HAL_CRYP_Encrypt() or HAL_CRYP_Decrypt() + without having to configure again the Key or the Initialization Vector between each API call, + the field KeyIVConfigSkip of the initialization structure must be set to CRYP_KEYIVCONFIG_ONCE. + Same is true for consecutive calls of HAL_CRYP_Encrypt_IT(), HAL_CRYP_Decrypt_IT(), HAL_CRYP_Encrypt_DMA() + or HAL_CRYP_Decrypt_DMA(). + + [..] + The cryptographic processor supports following standards: + (#) The data encryption standard (DES) and Triple-DES (TDES) supported only by CRYP1 IP: + (##)64-bit data block processing + (##) chaining modes supported : + (+++) Electronic Code Book(ECB) + (+++) Cipher Block Chaining (CBC) + (##) keys length supported :64-bit, 128-bit and 192-bit. + (#) The advanced encryption standard (AES) supported by CRYP1 & TinyAES IP: + (##)128-bit data block processing + (##) chaining modes supported : + (+++) Electronic Code Book(ECB) + (+++) Cipher Block Chaining (CBC) + (+++) Counter mode (CTR) + (+++) Galois/counter mode (GCM/GMAC) + (+++) Counter with Cipher Block Chaining-Message(CCM) + (##) keys length Supported : + (+++) for CRYP1 IP: 128-bit, 192-bit and 256-bit. + (+++) for TinyAES IP: 128-bit and 256-bit + + [..] This section describes the AES Galois/counter mode (GCM) supported by both CRYP1 IP: + (#) Algorithm supported : + (##) Galois/counter mode (GCM) + (##) Galois message authentication code (GMAC) :is exactly the same as + GCM algorithm composed only by an header. + (#) Four phases are performed in GCM : + (##) Init phase: IP prepares the GCM hash subkey (H) and do the IV processing + (##) Header phase: IP processes the Additional Authenticated Data (AAD), with hash + computation only. + (##) Payload phase: IP processes the plaintext (P) with hash computation + keystream + encryption + data XORing. It works in a similar way for ciphertext (C). + (##) Final phase: IP generates the authenticated tag (T) using the last block of data. + (#) structure of message construction in GCM is defined as below : + (##) 16 bytes Initial Counter Block (ICB)composed of IV and counter + (##) The authenticated header A (also knows as Additional Authentication Data AAD) + this part of the message is only authenticated, not encrypted. + (##) The plaintext message P is both authenticated and encrypted as ciphertext. + GCM standard specifies that ciphertext has same bit length as the plaintext. + (##) The last block is composed of the length of A (on 64 bits) and the length of ciphertext + (on 64 bits) + + [..] This section describe The AES Counter with Cipher Block Chaining-Message + Authentication Code (CCM) supported by both CRYP1 IP: + (#) Specific parameters for CCM : + + (##) B0 block : According to NIST Special Publication 800-38C, + The first block B0 is formatted as follows, where l(m) is encoded in + most-significant-byte first order(see below table 3) + + (+++) Q: a bit string representation of the octet length of P (plaintext) + (+++) q The octet length of the binary representation of the octet length of the payload + (+++) A nonce (N), n The octet length of the where n+q=15. + (+++) Flags: most significant octet containing four flags for control information, + (+++) t The octet length of the MAC. + (##) B1 block (header) : associated data length(a) concatenated with Associated Data (A) + the associated data length expressed in bytes (a) defined as below: + (+++) If 0 < a < 216-28, then it is encoded as [a]16, i.e. two octets + (+++) If 216-28 < a < 232, then it is encoded as 0xff || 0xfe || [a]32, i.e. six octets + (+++) If 232 < a < 264, then it is encoded as 0xff || 0xff || [a]64, i.e. ten octets + (##) CTRx block : control blocks + (+++) Generation of CTR1 from first block B0 information : + equal to B0 with first 5 bits zeroed and most significant bits storing octet + length of P also zeroed, then incremented by one ( see below Table 4) + (+++) Generation of CTR0: same as CTR1 with bit[0] set to zero. + + (#) Four phases are performed in CCM for CRYP1 IP: + (##) Init phase: IP prepares the GCM hash subkey (H) and do the IV processing + (##) Header phase: IP processes the Additional Authenticated Data (AAD), with hash + computation only. + (##) Payload phase: IP processes the plaintext (P) with hash computation + keystream + encryption + data XORing. It works in a similar way for ciphertext (C). + (##) Final phase: IP generates the authenticated tag (T) using the last block of data. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_CRYP_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_CRYP_RegisterCallback() or HAL_CRYP_RegisterXXXCallback() + to register an interrupt callback. + + Function HAL_CRYP_RegisterCallback() allows to register following callbacks: + (+) InCpltCallback : Input FIFO transfer completed callback. + (+) OutCpltCallback : Output FIFO transfer completed callback. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : CRYP MspInit. + (+) MspDeInitCallback : CRYP MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_CRYP_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_CRYP_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) InCpltCallback : Input FIFO transfer completed callback. + (+) OutCpltCallback : Output FIFO transfer completed callback. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : CRYP MspInit. + (+) MspDeInitCallback : CRYP MspDeInit. + + By default, after the HAL_CRYP_Init() and when the state is HAL_CRYP_STATE_RESET + all callbacks are set to the corresponding weak functions : + examples HAL_CRYP_InCpltCallback() , HAL_CRYP_OutCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_CRYP_Init()/ HAL_CRYP_DeInit() only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_CRYP_Init() / HAL_CRYP_DeInit() + keep and use the user MspInit/MspDeInit functions (registered beforehand) + + Callbacks can be registered/unregistered in HAL_CRYP_STATE_READY state only. + Exception done MspInit/MspDeInit callbacks that can be registered/unregistered + in HAL_CRYP_STATE_READY or HAL_CRYP_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_CRYP_RegisterCallback() before calling HAL_CRYP_DeInit() + or HAL_CRYP_Init() function. + + When The compilation define USE_HAL_CRYP_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + Table 1. Initial Counter Block (ICB) + +-------------------------------------------------------+ + | Initialization vector (IV) | Counter | + |----------------|----------------|-----------|---------| + 127 95 63 31 0 + + + Bit Number Register Contents + ---------- --------------- ----------- + 127 ...96 CRYP_IV1R[31:0] ICB[127:96] + 95 ...64 CRYP_IV1L[31:0] B0[95:64] + 63 ... 32 CRYP_IV0R[31:0] ICB[63:32] + 31 ... 0 CRYP_IV0L[31:0] ICB[31:0], where 32-bit counter= 0x2 + + Table 2. GCM last block definition + + +-------------------------------------------------------------------+ + | Bit[0] | Bit[32] | Bit[64] | Bit[96] | + |-----------|--------------------|-----------|----------------------| + | 0x0 | Header length[31:0]| 0x0 | Payload length[31:0] | + |-----------|--------------------|-----------|----------------------| + + Table 3. B0 block + Octet Number Contents + ------------ --------- + 0 Flags + 1 ... 15-q Nonce N + 16-q ... 15 Q + + the Flags field is formatted as follows: + + Bit Number Contents + ---------- ---------------------- + 7 Reserved (always zero) + 6 Adata + 5 ... 3 (t-2)/2 + 2 ... 0 [q-1]3 + + Table 4. CTRx block + Bit Number Register Contents + ---------- --------------- ----------- + 127 ...96 CRYP_IV1R[31:0] B0[127:96], where Q length bits are set to 0, except for + bit 0 that is set to 1 + 95 ...64 CRYP_IV1L[31:0] B0[95:64] + 63 ... 32 CRYP_IV0R[31:0] B0[63:32] + 31 ... 0 CRYP_IV0L[31:0] B0[31:0], where flag bits set to 0 + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined (AES) || defined (CRYP) + +/** @defgroup CRYP CRYP + * @brief CRYP HAL module driver. + * @{ + */ + + +#ifdef HAL_CRYP_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup CRYP_Private_Defines + * @{ + */ +#define CRYP_TIMEOUT_KEYPREPARATION 82U /*The latency of key preparation operation is 82 clock cycles.*/ +#define CRYP_TIMEOUT_GCMCCMINITPHASE 299U /* The latency of GCM/CCM init phase to prepare hash subkey is 299 clock cycles.*/ +#define CRYP_TIMEOUT_GCMCCMHEADERPHASE 290U /* The latency of GCM/CCM header phase is 290 clock cycles.*/ + +#define CRYP_PHASE_READY 0x00000001U /*!< CRYP peripheral is ready for initialization. */ +#define CRYP_PHASE_PROCESS 0x00000002U /*!< CRYP peripheral is in processing phase */ + +#if defined(AES) +#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode(Mode 1) */ +#define CRYP_OPERATINGMODE_KEYDERIVATION AES_CR_MODE_0 /*!< Key derivation mode only used when performing ECB and CBC decryptions (Mode 2) */ +#define CRYP_OPERATINGMODE_DECRYPT AES_CR_MODE_1 /*!< Decryption (Mode 3) */ +#define CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT AES_CR_MODE /*!< Key derivation and decryption only used when performing ECB and CBC decryptions (Mode 4) */ +#define CRYP_PHASE_INIT 0x00000000U /*!< GCM/GMAC (or CCM) init phase */ +#define CRYP_PHASE_HEADER AES_CR_GCMPH_0 /*!< GCM/GMAC or CCM header phase */ +#define CRYP_PHASE_PAYLOAD AES_CR_GCMPH_1 /*!< GCM(/CCM) payload phase */ +#define CRYP_PHASE_FINAL AES_CR_GCMPH /*!< GCM/GMAC or CCM final phase */ +#else /* CRYP */ +#define CRYP_PHASE_INIT 0x00000000U /*!< GCM/GMAC (or CCM) init phase */ +#define CRYP_PHASE_HEADER CRYP_CR_GCM_CCMPH_0 /*!< GCM/GMAC or CCM header phase */ +#define CRYP_PHASE_PAYLOAD CRYP_CR_GCM_CCMPH_1 /*!< GCM(/CCM) payload phase */ +#define CRYP_PHASE_FINAL CRYP_CR_GCM_CCMPH /*!< GCM/GMAC or CCM final phase */ +#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode */ +#define CRYP_OPERATINGMODE_DECRYPT CRYP_CR_ALGODIR /*!< Decryption */ +#endif /* End CRYP or AES */ + +/* CTR1 information to use in CCM algorithm */ +#define CRYP_CCM_CTR1_0 0x07FFFFFFU +#define CRYP_CCM_CTR1_1 0xFFFFFF00U +#define CRYP_CCM_CTR1_2 0x00000001U + + +/** + * @} + */ + + +/* Private macro -------------------------------------------------------------*/ +/** @addtogroup CRYP_Private_Macros + * @{ + */ + +#if defined(CRYP) + +#define CRYP_SET_PHASE(__HANDLE__, __PHASE__) do{(__HANDLE__)->Instance->CR &= (uint32_t)(~CRYP_CR_GCM_CCMPH);\ + (__HANDLE__)->Instance->CR |= (uint32_t)(__PHASE__);\ + }while(0) + +#define HAL_CRYP_FIFO_FLUSH(__HANDLE__) ((__HANDLE__)->Instance->CR |= CRYP_CR_FFLUSH) + +#else /*AES*/ +#define CRYP_SET_PHASE(__HANDLE__, __PHASE__) do{(__HANDLE__)->Instance->CR &= (uint32_t)(~AES_CR_GCMPH);\ + (__HANDLE__)->Instance->CR |= (uint32_t)(__PHASE__);\ + }while(0) +#endif /* End AES or CRYP*/ + + +/** + * @} + */ + +/* Private struct -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup CRYP_Private_Functions_prototypes + * @{ + */ + +static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr); +static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma); +static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma); +static void CRYP_DMAError(DMA_HandleTypeDef *hdma); +static void CRYP_SetKey(CRYP_HandleTypeDef *hcryp, uint32_t KeySize); +static void CRYP_AES_IT(CRYP_HandleTypeDef *hcryp); +#if defined (CRYP_CR_ALGOMODE_AES_GCM)|| defined (AES) +static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static void CRYP_GCMCCM_SetPayloadPhase_IT(CRYP_HandleTypeDef *hcryp); +static void CRYP_GCMCCM_SetHeaderPhase_IT(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase_DMA(CRYP_HandleTypeDef *hcryp); +static void CRYP_Workaround(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AESGCM_Process_DMA(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_AESGCM_Process_IT(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AESCCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AESCCM_Process_IT(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_AESCCM_Process_DMA(CRYP_HandleTypeDef *hcryp); +#endif /* AES or GCM CCM defined*/ +static void CRYP_AES_ProcessData(CRYP_HandleTypeDef *hcrypt, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AES_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AES_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_AES_Decrypt_IT(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_AES_Encrypt_IT(CRYP_HandleTypeDef *hcryp); +static HAL_StatusTypeDef CRYP_AES_Decrypt_DMA(CRYP_HandleTypeDef *hcryp); +#if defined (CRYP) +static void CRYP_TDES_IT(CRYP_HandleTypeDef *hcryp); +#if defined (CRYP_CR_ALGOMODE_AES_GCM) +static HAL_StatusTypeDef CRYP_WaitOnIFEMFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +#endif /* GCM CCM defined*/ +static HAL_StatusTypeDef CRYP_WaitOnBUSYFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_WaitOnOFNEFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +static HAL_StatusTypeDef CRYP_TDES_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +#else /*AES*/ +static HAL_StatusTypeDef CRYP_WaitOnCCFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout); +#endif /* End CRYP or AES */ + +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup CRYP_Exported_Functions CRYP Exported Functions + * @{ + */ + + +/** @defgroup CRYP_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions. + * +@verbatim + ======================================================================================== + ##### Initialization, de-initialization and Set and Get configuration functions ##### + ======================================================================================== + [..] This section provides functions allowing to: + (+) Initialize the CRYP + (+) DeInitialize the CRYP + (+) Initialize the CRYP MSP + (+) DeInitialize the CRYP MSP + (+) configure CRYP (HAL_CRYP_SetConfig) with the specified parameters in the CRYP_ConfigTypeDef + Parameters which are configured in This section are : + (+) Key size + (+) Data Type : 32,16, 8 or 1bit + (+) AlgoMode : + - for CRYP1 IP : + ECB and CBC in DES/TDES Standard + ECB,CBC,CTR,GCM/GMAC and CCM in AES Standard. + - for TinyAES2 IP, only ECB,CBC,CTR,GCM/GMAC and CCM in AES Standard are supported. + (+) Get CRYP configuration (HAL_CRYP_GetConfig) from the specified parameters in the CRYP_HandleTypeDef + + +@endverbatim + * @{ + */ + + +/** + * @brief Initializes the CRYP according to the specified + * parameters in the CRYP_ConfigTypeDef and creates the associated handle. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Init(CRYP_HandleTypeDef *hcryp) +{ + /* Check the CRYP handle allocation */ + if (hcryp == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_CRYP_KEYSIZE(hcryp->Init.KeySize)); + assert_param(IS_CRYP_DATATYPE(hcryp->Init.DataType)); + assert_param(IS_CRYP_ALGORITHM(hcryp->Init.Algorithm)); + assert_param(IS_CRYP_INIT(hcryp->Init.KeyIVConfigSkip)); + +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + if (hcryp->State == HAL_CRYP_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcryp->Lock = HAL_UNLOCKED; + + hcryp->InCpltCallback = HAL_CRYP_InCpltCallback; /* Legacy weak InCpltCallback */ + hcryp->OutCpltCallback = HAL_CRYP_OutCpltCallback; /* Legacy weak OutCpltCallback */ + hcryp->ErrorCallback = HAL_CRYP_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hcryp->MspInitCallback == NULL) + { + hcryp->MspInitCallback = HAL_CRYP_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware */ + hcryp->MspInitCallback(hcryp); + } +#else + if (hcryp->State == HAL_CRYP_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hcryp->Lock = HAL_UNLOCKED; + + /* Init the low level hardware */ + HAL_CRYP_MspInit(hcryp); + } +#endif /* (USE_HAL_CRYP_REGISTER_CALLBACKS) */ + + /* Set the key size(This bit field is don't care in the DES or TDES modes) data type and Algorithm */ +#if defined (CRYP) + + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_DATATYPE | CRYP_CR_KEYSIZE | CRYP_CR_ALGOMODE, + hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm); + +#else /*AES*/ + + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD, + hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm); + +#endif /* End AES or CRYP*/ + + /* Reset Error Code field */ + hcryp->ErrorCode = HAL_CRYP_ERROR_NONE; + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Set the default CRYP phase */ + hcryp->Phase = CRYP_PHASE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief De-Initializes the CRYP peripheral. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_DeInit(CRYP_HandleTypeDef *hcryp) +{ + /* Check the CRYP handle allocation */ + if (hcryp == NULL) + { + return HAL_ERROR; + } + + /* Set the default CRYP phase */ + hcryp->Phase = CRYP_PHASE_READY; + + /* Reset CrypInCount and CrypOutCount */ + hcryp->CrypInCount = 0; + hcryp->CrypOutCount = 0; + hcryp->CrypHeaderCount = 0; + + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + + if (hcryp->MspDeInitCallback == NULL) + { + hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit; /* Legacy weak MspDeInit */ + } + /* DeInit the low level hardware */ + hcryp->MspDeInitCallback(hcryp); + +#else + + /* DeInit the low level hardware: CLOCK, NVIC.*/ + HAL_CRYP_MspDeInit(hcryp); + +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hcryp); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Configure the CRYP according to the specified + * parameters in the CRYP_ConfigTypeDef + * @param hcryp: pointer to a CRYP_HandleTypeDef structure + * @param pConf: pointer to a CRYP_ConfigTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_SetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf) +{ + /* Check the CRYP handle allocation */ + if ((hcryp == NULL) || (pConf == NULL)) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_CRYP_KEYSIZE(pConf->KeySize)); + assert_param(IS_CRYP_DATATYPE(pConf->DataType)); + assert_param(IS_CRYP_ALGORITHM(pConf->Algorithm)); + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Set CRYP parameters */ + hcryp->Init.DataType = pConf->DataType; + hcryp->Init.pKey = pConf->pKey; + hcryp->Init.Algorithm = pConf->Algorithm; + hcryp->Init.KeySize = pConf->KeySize; + hcryp->Init.pInitVect = pConf->pInitVect; + hcryp->Init.Header = pConf->Header; + hcryp->Init.HeaderSize = pConf->HeaderSize; + hcryp->Init.B0 = pConf->B0; + hcryp->Init.DataWidthUnit = pConf->DataWidthUnit; + hcryp->Init.KeyIVConfigSkip = pConf->KeyIVConfigSkip; + hcryp->Init.HeaderWidthUnit = pConf->HeaderWidthUnit; + + /* Set the key size(This bit field is don't care in the DES or TDES modes) data type, AlgoMode and operating mode*/ +#if defined (CRYP) + + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_DATATYPE | CRYP_CR_KEYSIZE | CRYP_CR_ALGOMODE, + hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm); + +#else /*AES*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE | AES_CR_KEYSIZE | AES_CR_CHMOD, + hcryp->Init.DataType | hcryp->Init.KeySize | hcryp->Init.Algorithm); + + /*clear error flags*/ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_ERR_CLEAR); + +#endif /* End AES or CRYP */ + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + + /* Reset Error Code field */ + hcryp->ErrorCode = HAL_CRYP_ERROR_NONE; + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Set the default CRYP phase */ + hcryp->Phase = CRYP_PHASE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } +} + +/** + * @brief Get CRYP Configuration parameters in associated handle. + * @param pConf: pointer to a CRYP_ConfigTypeDef structure + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_GetConfig(CRYP_HandleTypeDef *hcryp, CRYP_ConfigTypeDef *pConf) +{ + /* Check the CRYP handle allocation */ + if ((hcryp == NULL) || (pConf == NULL)) + { + return HAL_ERROR; + } + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Get CRYP parameters */ + pConf->DataType = hcryp->Init.DataType; + pConf->pKey = hcryp->Init.pKey; + pConf->Algorithm = hcryp->Init.Algorithm; + pConf->KeySize = hcryp->Init.KeySize ; + pConf->pInitVect = hcryp->Init.pInitVect; + pConf->Header = hcryp->Init.Header ; + pConf->HeaderSize = hcryp->Init.HeaderSize; + pConf->B0 = hcryp->Init.B0; + pConf->DataWidthUnit = hcryp->Init.DataWidthUnit; + pConf->KeyIVConfigSkip = hcryp->Init.KeyIVConfigSkip; + pConf->HeaderWidthUnit = hcryp->Init.HeaderWidthUnit; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } +} +/** + * @brief Initializes the CRYP MSP. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval None + */ +__weak void HAL_CRYP_MspInit(CRYP_HandleTypeDef *hcryp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcryp); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRYP_MspInit can be implemented in the user file + */ +} + +/** + * @brief DeInitializes CRYP MSP. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval None + */ +__weak void HAL_CRYP_MspDeInit(CRYP_HandleTypeDef *hcryp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcryp); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRYP_MspDeInit can be implemented in the user file + */ +} + +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User CRYP Callback + * To be used instead of the weak predefined callback + * @param hcryp cryp handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_CRYP_INPUT_COMPLETE_CB_ID Input FIFO transfer completed callback ID + * @arg @ref HAL_CRYP_OUTPUT_COMPLETE_CB_ID Output FIFO transfer completed callback ID + * @arg @ref HAL_CRYP_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CRYP_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CRYP_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_CRYP_RegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID, + pCRYP_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hcryp); + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + switch (CallbackID) + { + case HAL_CRYP_INPUT_COMPLETE_CB_ID : + hcryp->InCpltCallback = pCallback; + break; + + case HAL_CRYP_OUTPUT_COMPLETE_CB_ID : + hcryp->OutCpltCallback = pCallback; + break; + + case HAL_CRYP_ERROR_CB_ID : + hcryp->ErrorCallback = pCallback; + break; + + case HAL_CRYP_MSPINIT_CB_ID : + hcryp->MspInitCallback = pCallback; + break; + + case HAL_CRYP_MSPDEINIT_CB_ID : + hcryp->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcryp->State == HAL_CRYP_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CRYP_MSPINIT_CB_ID : + hcryp->MspInitCallback = pCallback; + break; + + case HAL_CRYP_MSPDEINIT_CB_ID : + hcryp->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcryp); + + return status; +} + +/** + * @brief Unregister an CRYP Callback + * CRYP callback is redirected to the weak predefined callback + * @param hcryp cryp handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_CRYP_INPUT_COMPLETE_CB_ID Input FIFO transfer completed callback ID + * @arg @ref HAL_CRYP_OUTPUT_COMPLETE_CB_ID Output FIFO transfer completed callback ID + * @arg @ref HAL_CRYP_ERROR_CB_ID Error callback ID + * @arg @ref HAL_CRYP_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_CRYP_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_CRYP_UnRegisterCallback(CRYP_HandleTypeDef *hcryp, HAL_CRYP_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hcryp); + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + switch (CallbackID) + { + case HAL_CRYP_INPUT_COMPLETE_CB_ID : + hcryp->InCpltCallback = HAL_CRYP_InCpltCallback; /* Legacy weak InCpltCallback */ + break; + + case HAL_CRYP_OUTPUT_COMPLETE_CB_ID : + hcryp->OutCpltCallback = HAL_CRYP_OutCpltCallback; /* Legacy weak OutCpltCallback */ + break; + + case HAL_CRYP_ERROR_CB_ID : + hcryp->ErrorCallback = HAL_CRYP_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_CRYP_MSPINIT_CB_ID : + hcryp->MspInitCallback = HAL_CRYP_MspInit; + break; + + case HAL_CRYP_MSPDEINIT_CB_ID : + hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit; + break; + + default : + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hcryp->State == HAL_CRYP_STATE_RESET) + { + switch (CallbackID) + { + case HAL_CRYP_MSPINIT_CB_ID : + hcryp->MspInitCallback = HAL_CRYP_MspInit; + break; + + case HAL_CRYP_MSPDEINIT_CB_ID : + hcryp->MspDeInitCallback = HAL_CRYP_MspDeInit; + break; + + default : + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hcryp); + + return status; +} +#endif /* USE_HAL_UART_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup CRYP_Exported_Functions_Group2 Encrypt Decrypt functions + * @brief processing functions. + * +@verbatim + ============================================================================== + ##### Encrypt Decrypt functions ##### + ============================================================================== + [..] This section provides API allowing to Encrypt/Decrypt Data following + Standard DES/TDES or AES, and Algorithm configured by the user: + (+) Standard DES/TDES only supported by CRYP1 IP, below list of Algorithm supported : + - Electronic Code Book(ECB) + - Cipher Block Chaining (CBC) + (+) Standard AES supported by CRYP1 IP & TinyAES, list of Algorithm supported: + - Electronic Code Book(ECB) + - Cipher Block Chaining (CBC) + - Counter mode (CTR) + - Cipher Block Chaining (CBC) + - Counter mode (CTR) + - Galois/counter mode (GCM) + - Counter with Cipher Block Chaining-Message(CCM) + [..] Three processing functions are available: + (+) Polling mode : HAL_CRYP_Encrypt & HAL_CRYP_Decrypt + (+) Interrupt mode : HAL_CRYP_Encrypt_IT & HAL_CRYP_Decrypt_IT + (+) DMA mode : HAL_CRYP_Encrypt_DMA & HAL_CRYP_Decrypt_DMA + +@endverbatim + * @{ + */ + + +/** + * @brief Encryption mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (plaintext) + * @param Size: Length of the plaintext buffer in word. + * @param Output: Pointer to the output buffer(ciphertext) + * @param Timeout: Specify Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output, + uint32_t Timeout) +{ + uint32_t algo; + HAL_StatusTypeDef status; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr and pCrypOutBuffPtr parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + /* Set Encryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE; + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + + /*Set Initialization Vector (IV)*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Statrt DES/TDES encryption process */ + status = CRYP_TDES_Process(hcryp, Timeout); + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES encryption */ + status = CRYP_AES_Encrypt(hcryp, Timeout); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + + /* AES GCM encryption */ + status = CRYP_AESGCM_Process(hcryp, Timeout); + + break; + + case CRYP_AES_CCM: + + /* AES CCM encryption */ + status = CRYP_AESCCM_Process(hcryp, Timeout); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + +#else /*AES*/ + + /* Set the operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES encryption */ + status = CRYP_AES_Encrypt(hcryp, Timeout); + break; + + case CRYP_AES_GCM_GMAC: + + /* AES GCM encryption */ + status = CRYP_AESGCM_Process(hcryp, Timeout) ; + break; + + case CRYP_AES_CCM: + + /* AES CCM encryption */ + status = CRYP_AESCCM_Process(hcryp, Timeout); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } +#endif /*end AES or CRYP */ + + if (status == HAL_OK) + { + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Decryption mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (ciphertext ) + * @param Size: Length of the plaintext buffer in word. + * @param Output: Pointer to the output buffer(plaintext) + * @param Timeout: Specify Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output, + uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t algo; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr and pCrypOutBuffPtr parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + + /* Set Decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE; + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + + /*Set Initialization Vector (IV)*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Start DES/TDES decryption process */ + status = CRYP_TDES_Process(hcryp, Timeout); + + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt(hcryp, Timeout); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + + /* AES GCM decryption */ + status = CRYP_AESGCM_Process(hcryp, Timeout) ; + break; + + case CRYP_AES_CCM: + + /* AES CCM decryption */ + status = CRYP_AESCCM_Process(hcryp, Timeout); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + +#else /*AES*/ + + /* Set Decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt(hcryp, Timeout); + break; + + case CRYP_AES_GCM_GMAC: + + /* AES GCM decryption */ + status = CRYP_AESGCM_Process(hcryp, Timeout) ; + break; + + case CRYP_AES_CCM: + + /* AES CCM decryption */ + status = CRYP_AESCCM_Process(hcryp, Timeout); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } +#endif /* End AES or CRYP */ + + if (status == HAL_OK) + { + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Encryption in interrupt mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (plaintext) + * @param Size: Length of the plaintext buffer in word + * @param Output: Pointer to the output buffer(ciphertext) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Encrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output) +{ + uint32_t algo; + HAL_StatusTypeDef status = HAL_OK; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr and pCrypOutBuffPtr parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + + /* Set encryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = (hcryp->Instance->CR & CRYP_CR_ALGOMODE); + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + /* Set the Initialization Vector*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Enable CRYP to start DES/TDES process*/ + __HAL_CRYP_ENABLE(hcryp); + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + status = CRYP_AES_Encrypt_IT(hcryp); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + + status = CRYP_AESGCM_Process_IT(hcryp) ; + break; + + case CRYP_AES_CCM: + + status = CRYP_AESCCM_Process_IT(hcryp); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } + +#else /* AES */ + + /* Set encryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES encryption */ + status = CRYP_AES_Encrypt_IT(hcryp); + break; + + case CRYP_AES_GCM_GMAC: + + /* AES GCM encryption */ + status = CRYP_AESGCM_Process_IT(hcryp) ; + break; + + case CRYP_AES_CCM: + + /* AES CCM encryption */ + status = CRYP_AESCCM_Process_IT(hcryp); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } +#endif /*end AES or CRYP*/ + + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + status = HAL_ERROR; + } + + /* Return function status */ + return status; +} + +/** + * @brief Decryption in itnterrupt mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (ciphertext ) + * @param Size: Length of the plaintext buffer in word. + * @param Output: Pointer to the output buffer(plaintext) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Decrypt_IT(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output) +{ + uint32_t algo; + HAL_StatusTypeDef status = HAL_OK; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr and pCrypOutBuffPtr parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + + /* Set decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE; + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + + /* Set the Initialization Vector*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Enable CRYP and start DES/TDES process*/ + __HAL_CRYP_ENABLE(hcryp); + + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt_IT(hcryp); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + + /* AES GCM decryption */ + status = CRYP_AESGCM_Process_IT(hcryp) ; + break; + + case CRYP_AES_CCM: + + /* AES CCMdecryption */ + status = CRYP_AESCCM_Process_IT(hcryp); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } + +#else /*AES*/ + + /* Set decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt_IT(hcryp); + break; + + case CRYP_AES_GCM_GMAC: + + /* AES GCM decryption */ + status = CRYP_AESGCM_Process_IT(hcryp) ; + break; + + case CRYP_AES_CCM: + + /* AES CCM decryption */ + status = CRYP_AESCCM_Process_IT(hcryp); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } +#endif /* End AES or CRYP */ + + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + status = HAL_ERROR; + } + + /* Return function status */ + return status; +} + +/** + * @brief Encryption in DMA mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (plaintext) + * @param Size: Length of the plaintext buffer in word. + * @param Output: Pointer to the output buffer(ciphertext) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Encrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output) +{ + uint32_t algo; + HAL_StatusTypeDef status = HAL_OK; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr and pCrypOutBuffPtr parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + + /* Set encryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE; + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + + /* Set the Initialization Vector*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Start DMA process transfer for DES/TDES */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), ((uint16_t)(hcryp->Size) / 4U), + (uint32_t)(hcryp->pCrypOutBuffPtr)); + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the Initialization Vector*/ + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1U); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2U); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3U); + } + } /* if (DoKeyIVConfig == 1U) */ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Start DMA process transfer for AES */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), ((uint16_t)(hcryp->Size) / 4U), + (uint32_t)(hcryp->pCrypOutBuffPtr)); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + /* AES GCM encryption */ + status = CRYP_AESGCM_Process_DMA(hcryp) ; + break; + + case CRYP_AES_CCM: + /* AES CCM encryption */ + status = CRYP_AESCCM_Process_DMA(hcryp); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } + +#else /*AES*/ + /* Set encryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the Initialization Vector*/ + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); + } + } /* if (DoKeyIVConfig == 1U) */ + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Start DMA process transfer for AES */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr)); + break; + + case CRYP_AES_GCM_GMAC: + /* AES GCM encryption */ + status = CRYP_AESGCM_Process_DMA(hcryp) ; + break; + + case CRYP_AES_CCM: + /* AES CCM encryption */ + status = CRYP_AESCCM_Process_DMA(hcryp); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } +#endif /* End AES or CRYP */ + + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + status = HAL_ERROR; + } + + /* Return function status */ + return status; +} + +/** + * @brief Decryption in DMA mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Input: Pointer to the input buffer (ciphertext ) + * @param Size: Length of the plaintext buffer in word + * @param Output: Pointer to the output buffer(plaintext) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYP_Decrypt_DMA(CRYP_HandleTypeDef *hcryp, uint32_t *Input, uint16_t Size, uint32_t *Output) +{ + uint32_t algo; + HAL_StatusTypeDef status = HAL_OK; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + + /* Change state Busy */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Reset CrypInCount, CrypOutCount and Initialize pCrypInBuffPtr, pCrypOutBuffPtr and Size parameters*/ + hcryp->CrypInCount = 0U; + hcryp->CrypOutCount = 0U; + hcryp->pCrypInBuffPtr = Input; + hcryp->pCrypOutBuffPtr = Output; + + /* Calculate Size parameter in Byte*/ + if (hcryp->Init.DataWidthUnit == CRYP_DATAWIDTHUNIT_WORD) + { + hcryp->Size = Size * 4U; + } + else + { + hcryp->Size = Size; + } + +#if defined (CRYP) + + /* Set decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGODIR, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & CRYP_CR_ALGOMODE; + + switch (algo) + { + case CRYP_DES_ECB: + case CRYP_DES_CBC: + case CRYP_TDES_ECB: + case CRYP_TDES_CBC: + + /*Set Key */ + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + if ((hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + } + + /* Set the Initialization Vector*/ + if ((hcryp->Init.Algorithm == CRYP_DES_CBC) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + } + + /* Flush FIFO */ + HAL_CRYP_FIFO_FLUSH(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Start DMA process transfer for DES/TDES */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), ((uint16_t)(hcryp->Size) / 4U), + (uint32_t)(hcryp->pCrypOutBuffPtr)); + break; + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt_DMA(hcryp); + break; + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + case CRYP_AES_GCM: + /* AES GCM decryption */ + status = CRYP_AESGCM_Process_DMA(hcryp) ; + break; + + case CRYP_AES_CCM: + /* AES CCM decryption */ + status = CRYP_AESCCM_Process_DMA(hcryp); + break; + #endif /* GCM CCM defined*/ + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } + +#else /*AES*/ + + /* Set decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + + /* algo get algorithm selected */ + algo = hcryp->Instance->CR & AES_CR_CHMOD; + + switch (algo) + { + + case CRYP_AES_ECB: + case CRYP_AES_CBC: + case CRYP_AES_CTR: + + /* AES decryption */ + status = CRYP_AES_Decrypt_DMA(hcryp); + break; + + case CRYP_AES_GCM_GMAC: + /* AES GCM decryption */ + status = CRYP_AESGCM_Process_DMA(hcryp) ; + break; + + case CRYP_AES_CCM: + /* AES CCM decryption */ + status = CRYP_AESCCM_Process_DMA(hcryp); + break; + + default: + hcryp->ErrorCode |= HAL_CRYP_ERROR_NOT_SUPPORTED; + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + status = HAL_ERROR; + break; + } +#endif /* End AES or CRYP */ + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + status = HAL_ERROR; + } + + /* Return function status */ + return status; +} + +/** + * @} + */ + +/** @defgroup CRYP_Exported_Functions_Group3 CRYP IRQ handler management + * @brief CRYP IRQ handler. + * +@verbatim + ============================================================================== + ##### CRYP IRQ handler management ##### + ============================================================================== +[..] This section provides CRYP IRQ handler and callback functions. + (+) HAL_CRYP_IRQHandler CRYP interrupt request + (+) HAL_CRYP_InCpltCallback input data transfer complete callback + (+) HAL_CRYP_OutCpltCallback output data transfer complete callback + (+) HAL_CRYP_ErrorCallback CRYP error callback + (+) HAL_CRYP_GetState return the CRYP state + (+) HAL_CRYP_GetError return the CRYP error code +@endverbatim + * @{ + */ + +/** + * @brief This function handles cryptographic interrupt request. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval None + */ +void HAL_CRYP_IRQHandler(CRYP_HandleTypeDef *hcryp) +{ + +#if defined (CRYP) + + uint32_t itstatus = hcryp->Instance->MISR; + + if ((itstatus & (CRYP_IT_INI | CRYP_IT_OUTI)) != 0U) + { + if ((hcryp->Init.Algorithm == CRYP_DES_ECB) || (hcryp->Init.Algorithm == CRYP_DES_CBC) + || (hcryp->Init.Algorithm == CRYP_TDES_ECB) || (hcryp->Init.Algorithm == CRYP_TDES_CBC)) + { + CRYP_TDES_IT(hcryp); /* DES or TDES*/ + } + else if ((hcryp->Init.Algorithm == CRYP_AES_ECB) || (hcryp->Init.Algorithm == CRYP_AES_CBC) + || (hcryp->Init.Algorithm == CRYP_AES_CTR)) + { + CRYP_AES_IT(hcryp); /*AES*/ + } + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + else if ((hcryp->Init.Algorithm == CRYP_AES_GCM) || (hcryp->Init.Algorithm == CRYP_CR_ALGOMODE_AES_CCM)) + { + /* if header phase */ + if ((hcryp->Instance->CR & CRYP_PHASE_HEADER) == CRYP_PHASE_HEADER) + { + CRYP_GCMCCM_SetHeaderPhase_IT(hcryp); + } + else /* if payload phase */ + { + CRYP_GCMCCM_SetPayloadPhase_IT(hcryp); + } + } + #endif /* GCM CCM defined*/ + else + { + /* Nothing to do */ + } + } + +#else /*AES*/ + if (__HAL_CRYP_GET_FLAG(hcryp, CRYP_IT_CCF) != RESET) + { + if (__HAL_CRYP_GET_IT_SOURCE(hcryp, CRYP_IT_CCFIE) != RESET) + { + + /* Clear computation complete flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + + /* if header phase */ + if ((hcryp->Instance->CR & CRYP_PHASE_HEADER) == CRYP_PHASE_HEADER) + { + CRYP_GCMCCM_SetHeaderPhase_IT(hcryp); + } + else /* if payload phase */ + { + CRYP_GCMCCM_SetPayloadPhase_IT(hcryp); + } + } + else if (hcryp->Init.Algorithm == CRYP_AES_CCM) + { + /* if header phase */ + if (hcryp->Init.HeaderSize >= hcryp->CrypHeaderCount) + { + CRYP_GCMCCM_SetHeaderPhase_IT(hcryp); + } + else /* if payload phase */ + { + CRYP_GCMCCM_SetPayloadPhase_IT(hcryp); + } + } + else /* AES Algorithm ECB,CBC or CTR*/ + { + CRYP_AES_IT(hcryp); + } + } + } + /* Check if error occurred */ + if (__HAL_CRYP_GET_IT_SOURCE(hcryp, CRYP_IT_ERRIE) != RESET) + { + /* If write Error occurred */ + if (__HAL_CRYP_GET_FLAG(hcryp, CRYP_IT_WRERR) != RESET) + { + hcryp->ErrorCode |= HAL_CRYP_ERROR_WRITE; + } + /* If read Error occurred */ + if (__HAL_CRYP_GET_FLAG(hcryp, CRYP_IT_RDERR) != RESET) + { + hcryp->ErrorCode |= HAL_CRYP_ERROR_READ; + } + } +#endif /* End AES or CRYP */ +} + +/** + * @brief Return the CRYP error code. + * @param hcryp : pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for the CRYP IP + * @retval CRYP error code + */ +uint32_t HAL_CRYP_GetError(CRYP_HandleTypeDef *hcryp) +{ + return hcryp->ErrorCode; +} + +/** + * @brief Returns the CRYP state. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval HAL state + */ +HAL_CRYP_STATETypeDef HAL_CRYP_GetState(CRYP_HandleTypeDef *hcryp) +{ + return hcryp->State; +} + +/** + * @brief Input FIFO transfer completed callback. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval None + */ +__weak void HAL_CRYP_InCpltCallback(CRYP_HandleTypeDef *hcryp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcryp); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRYP_InCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Output FIFO transfer completed callback. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval None + */ +__weak void HAL_CRYP_OutCpltCallback(CRYP_HandleTypeDef *hcryp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcryp); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_CRYP_OutCpltCallback can be implemented in the user file + */ +} + +/** + * @brief CRYP error callback. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval None + */ +__weak void HAL_CRYP_ErrorCallback(CRYP_HandleTypeDef *hcryp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hcryp); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_CRYP_ErrorCallback could be implemented in the user file + */ +} +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup CRYP_Private_Functions + * @{ + */ + +#if defined (CRYP) + +/** + * @brief Encryption in ECB/CBC Algorithm with DES/TDES standard. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Timeout: specify Timeout value + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_TDES_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t temp[2]; /* Temporary CrypOutBuff */ + uint16_t incount; /* Temporary CrypInCount Value */ + uint16_t outcount; /* Temporary CrypOutCount Value */ + uint32_t i; + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + /*Start processing*/ + while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U))) + { + /* Temporary CrypInCount Value */ + incount = hcryp->CrypInCount; + /* Write plain data and get cipher data */ + if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < (hcryp->Size / 4U))) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + + /* Wait for OFNE flag to be raised */ + if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state & errorCode*/ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < (hcryp->Size / 4U))) + { + /* Read the output block from the Output FIFO and put them in temporary Buffer then get CrypOutBuff from temporary buffer */ + for (i = 0U; i < 2U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + i = 0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 2U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + } + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + } + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief CRYP block input/output data handling under interruption with DES/TDES standard. + * @note The function is called under interruption only, once + * interruptions have been enabled by CRYP_Decrypt_IT() and CRYP_Encrypt_IT(). + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval none + */ +static void CRYP_TDES_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t temp[2]; /* Temporary CrypOutBuff */ + uint32_t i; + + if (hcryp->State == HAL_CRYP_STATE_BUSY) + { + if (__HAL_CRYP_GET_IT(hcryp, CRYP_IT_INI) != 0x0U) + { + if (__HAL_CRYP_GET_FLAG(hcryp, CRYP_FLAG_INRIS) != 0x0U) + { + /* Write input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + + if (hcryp->CrypInCount == ((uint16_t)(hcryp->Size) / 4U)) + { + /* Disable interruption */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI); + /* Call the input data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + } + if (__HAL_CRYP_GET_IT(hcryp, CRYP_IT_OUTI) != 0x0U) + { + if (__HAL_CRYP_GET_FLAG(hcryp, CRYP_FLAG_OUTRIS) != 0x0U) + { + /* Read the output block from the Output FIFO and put them in temporary Buffer then get CrypOutBuff from temporary buffer */ + for (i = 0U; i < 2U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + i = 0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 2U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + if (hcryp->CrypOutCount == ((uint16_t)(hcryp->Size) / 4U)) + { + /* Disable interruption */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI); + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + /* Call output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } +} + +#endif /* CRYP */ + +/** + * @brief Encryption in ECB/CBC & CTR Algorithm with AES Standard + * @param hcryp: pointer to a CRYP_HandleTypeDef structure + * @param Timeout: specify Timeout value + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AES_Encrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint16_t outcount; /* Temporary CrypOutCount Value */ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + /* Set the Initialization Vector*/ +#if defined (AES) + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#else /* CRYP */ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#endif /* End AES or CRYP */ + } + } /* if (DoKeyIVConfig == 1U) */ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U))) + { + /* Write plain Ddta and get cipher data */ + CRYP_AES_ProcessData(hcryp, Timeout); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + } + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Encryption in ECB/CBC & CTR mode with AES Standard using interrupt mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AES_Encrypt_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + /* Set the Initialization Vector*/ +#if defined (AES) + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); + +#else /* CRYP */ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#endif /* End AES or CRYP */ + } + } /* if (DoKeyIVConfig == 1U) */ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + if (hcryp->Size != 0U) + { +#if defined (AES) + + /* Enable computation complete flag and error interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Increment the pointer before writing the input block in the IN FIFO to make sure that + when Computation Completed IRQ fires, the hcryp->CrypInCount has always a consistent value + and it is ready for the next operation. */ + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + +#else /* CRYP */ + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + +#endif /* End AES or CRYP */ + } + else + { + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Decryption in ECB/CBC & CTR mode with AES Standard + * @param hcryp: pointer to a CRYP_HandleTypeDef structure + * @param Timeout: Specify Timeout value + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AES_Decrypt(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint16_t outcount; /* Temporary CrypOutCount Value */ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + /* Key preparation for ECB/CBC */ + if (hcryp->Init.Algorithm != CRYP_AES_CTR) + { +#if defined (AES) + if (hcryp->AutoKeyDerivation == DISABLE)/*Mode 2 Key preparation*/ + { + /* Set key preparation for decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for CCF flag to be raised */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state & error code*/ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Return to decryption operating mode(Mode 3)*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + } + else /*Mode 4 : decryption & Key preparation*/ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set decryption & Key preparation operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT); + } +#else /* CRYP */ + /* change ALGOMODE to key preparation for decryption*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for BUSY flag to be raised */ + if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Turn back to ALGOMODE of the configuration */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm); + +#endif /* End AES or CRYP */ + } + else /*Algorithm CTR */ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + } + + /* Set IV */ + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + /* Set the Initialization Vector*/ +#if defined (AES) + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#else /* CRYP */ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#endif /* End AES or CRYP */ + } + } /* if (DoKeyIVConfig == 1U) */ + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + while ((hcryp->CrypInCount < (hcryp->Size / 4U)) && (outcount < (hcryp->Size / 4U))) + { + /* Write plain data and get cipher data */ + CRYP_AES_ProcessData(hcryp, Timeout); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + } + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Return function status */ + return HAL_OK; +} +/** + * @brief Decryption in ECB/CBC & CTR mode with AES Standard using interrupt mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AES_Decrypt_IT(CRYP_HandleTypeDef *hcryp) +{ + __IO uint32_t count = 0U; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + + if (DoKeyIVConfig == 1U) + { + /* Key preparation for ECB/CBC */ + if (hcryp->Init.Algorithm != CRYP_AES_CTR) + { +#if defined (AES) + if (hcryp->AutoKeyDerivation == DISABLE)/*Mode 2 Key preparation*/ + { + /* Set key preparation for decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for CCF flag to be raised */ + count = CRYP_TIMEOUT_KEYPREPARATION; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Return to decryption operating mode(Mode 3)*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + } + else /*Mode 4 : decryption & key preparation*/ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set decryption & key preparation operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT); + } +#else /* CRYP */ + + /* change ALGOMODE to key preparation for decryption*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for BUSY flag to be raised */ + count = CRYP_TIMEOUT_KEYPREPARATION; + do + { + count-- ; + if (count == 0U) + { + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY)); + + /* Turn back to ALGOMODE of the configuration */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm); + +#endif /* End AES or CRYP */ + } + + else /*Algorithm CTR */ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + } + + /* Set IV */ + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + /* Set the Initialization Vector*/ +#if defined (AES) + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#else /* CRYP */ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#endif /* End AES or CRYP */ + } + } /* if (DoKeyIVConfig == 1U) */ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + if (hcryp->Size != 0U) + { + +#if defined (AES) + + /* Enable computation complete flag and error interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Increment the pointer before writing the input block in the IN FIFO to make sure that + when Computation Completed IRQ fires, the hcryp->CrypInCount has always a consistent value + and it is ready for the next operation. */ + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + (hcryp->CrypInCount - 1U)); + +#else /* CRYP */ + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + +#endif /* End AES or CRYP */ + } + else + { + /* Process locked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + } + + /* Return function status */ + return HAL_OK; +} +/** + * @brief Decryption in ECB/CBC & CTR mode with AES Standard using DMA mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AES_Decrypt_DMA(CRYP_HandleTypeDef *hcryp) +{ + __IO uint32_t count = 0U; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + } + } + if (DoKeyIVConfig == 1U) + { + /* Key preparation for ECB/CBC */ + if (hcryp->Init.Algorithm != CRYP_AES_CTR) + { +#if defined (AES) + if (hcryp->AutoKeyDerivation == DISABLE)/*Mode 2 key preparation*/ + { + /* Set key preparation for decryption operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for CCF flag to be raised */ + count = CRYP_TIMEOUT_KEYPREPARATION; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Return to decryption operating mode(Mode 3)*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_DECRYPT); + } + else /*Mode 4 : decryption & key preparation*/ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set decryption & Key preparation operating mode*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT); + } +#else /* CRYP */ + /* change ALGOMODE to key preparation for decryption*/ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_CR_ALGOMODE_AES_KEY); + + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Wait for BUSY flag to be raised */ + count = CRYP_TIMEOUT_KEYPREPARATION; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY)); + + /* Turn back to ALGOMODE of the configuration */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, hcryp->Init.Algorithm); + +#endif /* End AES or CRYP */ + } + else /*Algorithm CTR */ + { + /* Set the Key*/ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + } + + if (hcryp->Init.Algorithm != CRYP_AES_ECB) + { + /* Set the Initialization Vector*/ +#if defined (AES) + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#else /* CRYP */ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); +#endif /* End AES or CRYP */ + } + } /* if (DoKeyIVConfig == 1U) */ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + if (hcryp->Size != 0U) + { + /* Set the input and output addresses and start DMA transfer */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + } + + /* Return function status */ + return HAL_OK; +} + + +/** + * @brief DMA CRYP input data process complete callback. + * @param hdma: DMA handle + * @retval None + */ +static void CRYP_DMAInCplt(DMA_HandleTypeDef *hdma) +{ + CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable the DMA transfer for input FIFO request by resetting the DIEN bit + in the DMACR register */ +#if defined (CRYP) + hcryp->Instance->DMACR &= (uint32_t)(~CRYP_DMACR_DIEN); + +#else /* AES */ + CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAINEN); + + /* TinyAES2, No output on CCM AES, unlock should be done when input data process complete */ + if ((hcryp->Init.Algorithm & CRYP_AES_CCM) == CRYP_AES_CCM) + { + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Change the CRYP state to ready */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + } +#endif /* End AES or CRYP */ + + /* Call input data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA CRYP output data process complete callback. + * @param hdma: DMA handle + * @retval None + */ +static void CRYP_DMAOutCplt(DMA_HandleTypeDef *hdma) +{ + CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable the DMA transfer for output FIFO request by resetting + the DOEN bit in the DMACR register */ + +#if defined (CRYP) + + hcryp->Instance->DMACR &= (uint32_t)(~CRYP_DMACR_DOEN); + #if defined (CRYP_CR_ALGOMODE_AES_GCM) + if ((hcryp->Init.Algorithm & CRYP_AES_GCM) != CRYP_AES_GCM) + { + /* Disable CRYP (not allowed in GCM)*/ + __HAL_CRYP_DISABLE(hcryp); + } + + #else /*NO GCM CCM */ + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + #endif /* GCM CCM defined*/ +#else /* AES */ + + CLEAR_BIT(hcryp->Instance->CR, AES_CR_DMAOUTEN); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + if ((hcryp->Init.Algorithm & CRYP_AES_GCM_GMAC) != CRYP_AES_GCM_GMAC) + { + /* Disable CRYP (not allowed in GCM)*/ + __HAL_CRYP_DISABLE(hcryp); + } +#endif /* End AES or CRYP */ + + /* Change the CRYP state to ready */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + /* Call output data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA CRYP communication error callback. + * @param hdma: DMA handle + * @retval None + */ +static void CRYP_DMAError(DMA_HandleTypeDef *hdma) +{ + CRYP_HandleTypeDef *hcryp = (CRYP_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* DMA error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA; + +#if defined (AES) + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* AES */ + + /* Call error callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ +} + +/** + * @brief Set the DMA configuration and start the DMA transfer + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param inputaddr: address of the input buffer + * @param Size: size of the input buffer, must be a multiple of 16. + * @param outputaddr: address of the output buffer + * @retval None + */ +static void CRYP_SetDMAConfig(CRYP_HandleTypeDef *hcryp, uint32_t inputaddr, uint16_t Size, uint32_t outputaddr) +{ + /* Set the CRYP DMA transfer complete callback */ + hcryp->hdmain->XferCpltCallback = CRYP_DMAInCplt; + + /* Set the DMA input error callback */ + hcryp->hdmain->XferErrorCallback = CRYP_DMAError; + + /* Set the CRYP DMA transfer complete callback */ + hcryp->hdmaout->XferCpltCallback = CRYP_DMAOutCplt; + + /* Set the DMA output error callback */ + hcryp->hdmaout->XferErrorCallback = CRYP_DMAError; + +#if defined (CRYP) + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + + /* Enable the input DMA Stream */ + if (HAL_DMA_Start_IT(hcryp->hdmain, inputaddr, (uint32_t)&hcryp->Instance->DIN, Size) != HAL_OK) + { + /* DMA error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA; + + /* Call error callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + /* Enable the output DMA Stream */ + if (HAL_DMA_Start_IT(hcryp->hdmaout, (uint32_t)&hcryp->Instance->DOUT, outputaddr, Size) != HAL_OK) + { + /* DMA error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA; + + /* Call error callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + /* Enable In/Out DMA request */ + hcryp->Instance->DMACR = CRYP_DMACR_DOEN | CRYP_DMACR_DIEN; + +#else /* AES */ + + if (((hcryp->Init.Algorithm & CRYP_AES_GCM_GMAC) != CRYP_AES_GCM_GMAC) + && ((hcryp->Init.Algorithm & CRYP_AES_CCM) != CRYP_AES_CCM)) + { + /* Enable CRYP (not allowed in GCM & CCM)*/ + __HAL_CRYP_ENABLE(hcryp); + } + + /* Enable the DMA input stream */ + if (HAL_DMA_Start_IT(hcryp->hdmain, inputaddr, (uint32_t)&hcryp->Instance->DINR, Size) != HAL_OK) + { + /* DMA error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA; + + /* Call error callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + /* Enable the DMA output stream */ + if (HAL_DMA_Start_IT(hcryp->hdmaout, (uint32_t)&hcryp->Instance->DOUTR, outputaddr, Size) != HAL_OK) + { + /* DMA error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_DMA; + + /* Call error callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + /*AES2v1.1.1 : CCM authentication : no init phase, only header and final phase */ + /* Enable In and Out DMA requests */ + if ((hcryp->Init.Algorithm & CRYP_AES_CCM) == CRYP_AES_CCM) + { + /* Enable only In DMA requests for CCM*/ + SET_BIT(hcryp->Instance->CR, (AES_CR_DMAINEN)); + } + else + { + /* Enable In and Out DMA requests */ + SET_BIT(hcryp->Instance->CR, (AES_CR_DMAINEN | AES_CR_DMAOUTEN)); + } +#endif /* End AES or CRYP */ +} + +/** + * @brief Process Data: Write Input data in polling mode and used in AES functions. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Timeout: Specify Timeout value + * @retval None + */ +static void CRYP_AES_ProcessData(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + + uint32_t temp[4]; /* Temporary CrypOutBuff */ + uint32_t i; +#if defined (CRYP) + uint16_t incount; /* Temporary CrypInCount Value */ + uint16_t outcount; /* Temporary CrypOutCount Value */ +#endif + +#if defined (CRYP) + + /*Temporary CrypOutCount Value*/ + incount = hcryp->CrypInCount; + + if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < (hcryp->Size / 4U))) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + + /* Wait for OFNE flag to be raised */ + if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state & error code*/ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < (hcryp->Size / 4U))) + { + /* Read the output block from the Output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + i = 0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + } + +#else /* AES */ + + /* Write the input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + + /* Wait for CCF flag to be raised */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer*/ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUTR; + } + i = 0U; + while ((hcryp->CrypOutCount < ((hcryp->Size + 3U) / 4U)) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } +#endif /* End AES or CRYP */ +} + +/** + * @brief Handle CRYP block input/output data handling under interruption. + * @note The function is called under interruption only, once + * interruptions have been enabled by HAL_CRYP_Encrypt_IT or HAL_CRYP_Decrypt_IT. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @retval HAL status + */ +static void CRYP_AES_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t temp[4]; /* Temporary CrypOutBuff */ + uint32_t i; +#if defined (CRYP) + uint16_t incount; /* Temporary CrypInCount Value */ + uint16_t outcount; /* Temporary CrypOutCount Value */ +#endif + + if (hcryp->State == HAL_CRYP_STATE_BUSY) + { +#if defined (CRYP) + + /*Temporary CrypOutCount Value*/ + incount = hcryp->CrypInCount; + if (((hcryp->Instance->SR & CRYP_FLAG_IFNF) != 0x0U) && (incount < (hcryp->Size / 4U))) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + if (hcryp->CrypInCount == ((uint16_t)(hcryp->Size) / 4U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI); + + /* Call the input data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + if (((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) && (outcount < (hcryp->Size / 4U))) + { + /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + i = 0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + if (hcryp->CrypOutCount == ((uint16_t)(hcryp->Size) / 4U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Call Output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + +#else /*AES*/ + + /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer*/ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUTR; + } + i = 0U; + while ((hcryp->CrypOutCount < ((hcryp->Size + 3U) / 4U)) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + + if (hcryp->CrypOutCount == (hcryp->Size / 4U)) + { + /* Disable Computation Complete flag and errors interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + + /* Call Output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + else + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + + if (hcryp->CrypInCount == (hcryp->Size / 4U)) + { + /* Call Input transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } +#endif /* End AES or CRYP */ + + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Writes Key in Key registers. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param KeySize: Size of Key + * @retval None + */ +static void CRYP_SetKey(CRYP_HandleTypeDef *hcryp, uint32_t KeySize) +{ +#if defined (CRYP) + + switch (KeySize) + { + case CRYP_KEYSIZE_256B: + hcryp->Instance->K0LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K0RR = *(uint32_t *)(hcryp->Init.pKey + 1); + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 5); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 6); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 7); + break; + case CRYP_KEYSIZE_192B: + hcryp->Instance->K1LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K1RR = *(uint32_t *)(hcryp->Init.pKey + 1); + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 5); + break; + case CRYP_KEYSIZE_128B: + hcryp->Instance->K2LR = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->K2RR = *(uint32_t *)(hcryp->Init.pKey + 1); + hcryp->Instance->K3LR = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->K3RR = *(uint32_t *)(hcryp->Init.pKey + 3); + + break; + default: + break; + } +#else /*AES*/ + switch (KeySize) + { + case CRYP_KEYSIZE_256B: + hcryp->Instance->KEYR7 = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->KEYR6 = *(uint32_t *)(hcryp->Init.pKey + 1); + hcryp->Instance->KEYR5 = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->KEYR4 = *(uint32_t *)(hcryp->Init.pKey + 3); + hcryp->Instance->KEYR3 = *(uint32_t *)(hcryp->Init.pKey + 4); + hcryp->Instance->KEYR2 = *(uint32_t *)(hcryp->Init.pKey + 5); + hcryp->Instance->KEYR1 = *(uint32_t *)(hcryp->Init.pKey + 6); + hcryp->Instance->KEYR0 = *(uint32_t *)(hcryp->Init.pKey + 7); + break; + case CRYP_KEYSIZE_128B: + hcryp->Instance->KEYR3 = *(uint32_t *)(hcryp->Init.pKey); + hcryp->Instance->KEYR2 = *(uint32_t *)(hcryp->Init.pKey + 1); + hcryp->Instance->KEYR1 = *(uint32_t *)(hcryp->Init.pKey + 2); + hcryp->Instance->KEYR0 = *(uint32_t *)(hcryp->Init.pKey + 3); + + break; + default: + break; + } +#endif /* End AES or CRYP */ +} + +#if defined (CRYP_CR_ALGOMODE_AES_GCM)|| defined (AES) +/** + * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Timeout: Timeout duration + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESGCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U ; + uint16_t outcount; /* Temporary CrypOutCount Value */ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + if (DoKeyIVConfig == 1U) + { + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + + /****************************** Init phase **********************************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + +#if defined(CRYP) + + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /*Wait for the CRYPEN bit to be cleared*/ + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + +#else /* AES */ + /* Workaround 1 : only AES. + Datatype configuration must be 32 bits during Init phase. Only, after Init, and before re + enabling the IP, datatype different from 32 bits can be configured.*/ + /* Select DATATYPE 32 */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, CRYP_DATATYPE_32B); + + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* just wait for hash computation */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked & return error */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* End AES or CRYP */ + + /************************ Header phase *************************************/ + + if (CRYP_GCMCCM_SetHeaderPhase(hcryp, Timeout) != HAL_OK) + { + return HAL_ERROR; + } + + /*************************Payload phase ************************************/ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + +#if defined(CRYP) + + /* Disable the CRYP peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + +#else /* AES */ + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + +#endif /* End AES or CRYP */ + } /* if (DoKeyIVConfig == 1U) */ + + if ((hcryp->Size % 16U) != 0U) + { + /* recalculate wordsize */ + wordsize = ((wordsize / 4U) * 4U) ; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + /* Write input data and get output Data */ + while ((hcryp->CrypInCount < wordsize) && (outcount < wordsize)) + { + /* Write plain data and get cipher data */ + CRYP_AES_ProcessData(hcryp, Timeout); + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state & error code */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + if ((hcryp->Size % 16U) != 0U) + { + /* Workaround 2 : CRYP1 & AES generates correct TAG for GCM mode only when input block size is multiple of + 128 bits. If lthe size of the last block of payload is inferior to 128 bits, when GCM encryption + is selected, then the TAG message will be wrong.*/ + CRYP_Workaround(hcryp, Timeout); + } + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG in interrupt mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESGCM_Process_IT(CRYP_HandleTypeDef *hcryp) +{ + __IO uint32_t count = 0U; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ +#if defined(AES) + uint32_t loopcounter; + uint32_t lastwordsize; + uint32_t npblb; +#endif /* AES */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + /* Configure Key, IV and process message (header and payload) */ + if (DoKeyIVConfig == 1U) + { + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + + /******************************* Init phase *********************************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + +#if defined(CRYP) + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Wait for the CRYPEN bit to be cleared*/ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN); + +#else /* AES */ + + /* Workaround 1 : only AES + Datatype configuration must be 32 bits during INIT phase. Only, after INIT, and before re + enabling the IP, datatype different from 32 bits can be configured.*/ + /* Select DATATYPE 32 */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, CRYP_DATATYPE_32B); + + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* just wait for hash computation */ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* End AES or CRYP */ + + /***************************** Header phase *********************************/ + +#if defined(CRYP) + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + +#else /* AES */ + + /* Workaround 1: only AES , before re-enabling the IP, datatype can be configured*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, hcryp->Init.DataType); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable computation complete flag and error interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + if (hcryp->Init.HeaderSize == 0U) /*header phase is skipped*/ + { + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Select payload phase once the header phase is performed */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_PAYLOAD); + + /* Write the payload Input block in the IN FIFO */ + if (hcryp->Size == 0U) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + else if (hcryp->Size >= 16U) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + if (hcryp->CrypInCount == (hcryp->Size / 4U)) + { + /* Call Input transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + else /* Size < 16Bytes : first block is the last block*/ + { + /* Workaround not implemented*/ + /* Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption: + Workaround is implemented in polling mode, so if last block of + payload <128bit don't use CRYP_Encrypt_IT otherwise TAG is incorrectly generated for GCM Encryption. */ + + /* Compute the number of padding bytes in last block of payload */ + npblb = 16U - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + + /* last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize ; loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + } + else if ((hcryp->Init.HeaderSize) < 4U) + { + for (loopcounter = 0U; loopcounter < hcryp->Init.HeaderSize ; loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + while (loopcounter < 4U) + { + /* pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + /* Call Input transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + else if ((hcryp->Init.HeaderSize) >= 4U) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + } + else + { + /* Nothing to do */ + } + +#endif /* End AES or CRYP */ + } /* end of if (DoKeyIVConfig == 1U) */ + + /* Return function status */ + return HAL_OK; +} + + +/** + * @brief Encryption/Decryption process in AES GCM mode and prepare the authentication TAG using DMA + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESGCM_Process_DMA(CRYP_HandleTypeDef *hcryp) +{ + __IO uint32_t count = 0U; + uint32_t wordsize; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + if (DoKeyIVConfig == 1U) + { + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + + /*************************** Init phase ************************************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + +#if defined(CRYP) + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IV0LR = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IV0RR = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IV1LR = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IV1RR = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Wait for the CRYPEN bit to be cleared*/ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN); + +#else /* AES */ + + /*Workaround 1 : only AES + Datatype configuration must be 32 bits during Init phase. Only, after Init, and before re + enabling the IP, datatype different from 32 bits can be configured.*/ + /* Select DATATYPE 32 */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, CRYP_DATATYPE_32B); + + /* Set the initialization vector and the counter : Initial Counter Block (ICB)*/ + hcryp->Instance->IVR3 = *(uint32_t *)(hcryp->Init.pInitVect); + hcryp->Instance->IVR2 = *(uint32_t *)(hcryp->Init.pInitVect + 1); + hcryp->Instance->IVR1 = *(uint32_t *)(hcryp->Init.pInitVect + 2); + hcryp->Instance->IVR0 = *(uint32_t *)(hcryp->Init.pInitVect + 3); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* just wait for hash computation */ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* End AES or CRYP */ + + /************************ Header phase *************************************/ + + if (CRYP_GCMCCM_SetHeaderPhase_DMA(hcryp) != HAL_OK) + { + return HAL_ERROR; + } + + /************************ Payload phase ************************************/ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + +#if defined(CRYP) + + /* Disable the CRYP peripheral */ + __HAL_CRYP_DISABLE(hcryp); + +#endif /* CRYP */ + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + } /* if (DoKeyIVConfig == 1U) */ + + if (hcryp->Size != 0U) + { + /* CRYP1 IP V < 2.2.1 Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption: + Workaround is implemented in polling mode, so if last block of + payload <128bit don't use DMA mode otherwise TAG is incorrectly generated . */ + /* Set the input and output addresses and start DMA transfer */ + if ((hcryp->Size % 16U) == 0U) + { + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + else /*to compute last word<128bits, otherwise it will not be encrypted/decrypted */ + { + wordsize = (uint32_t)(hcryp->Size) + (16U - ((uint32_t)(hcryp->Size) % 16U)) ; + + /* Set the input and output addresses and start DMA transfer, pCrypOutBuffPtr size should be %4 */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), ((uint16_t)wordsize / 4U), + (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + } + else + { + /* Process unLocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state and phase */ + hcryp->State = HAL_CRYP_STATE_READY; + } + + /* Return function status */ + return HAL_OK; +} + + +/** + * @brief AES CCM encryption/decryption processing in polling mode + * for TinyAES IP, no encrypt/decrypt performed, only authentication preparation. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Timeout: Timeout duration + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESCCM_Process(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t wordsize = (uint32_t)(hcryp->Size) / 4U; + uint16_t outcount; /* Temporary CrypOutCount Value */ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ +#if defined(AES) + uint32_t loopcounter; + uint32_t npblb; + uint32_t lastwordsize; +#endif /* AES */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + if (DoKeyIVConfig == 1U) + { + + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + +#if defined(CRYP) + + /********************** Init phase ******************************************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector (IV) with CTR1 information */ + hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0; + hcryp->Instance->IV0RR = hcryp->Init.B0[1]; + hcryp->Instance->IV1LR = hcryp->Init.B0[2]; + hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2; + + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write B0 packet into CRYP_DIN Register*/ + if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3); + } + /* Get tick */ + tickstart = HAL_GetTick(); + + /*Wait for the CRYPEN bit to be cleared*/ + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } +#else /* AES */ + /*AES2v1.1.1 : CCM authentication : no init phase, only header and final phase */ + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* configured encryption mode */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector with zero values*/ + hcryp->Instance->IVR3 = 0U; + hcryp->Instance->IVR2 = 0U; + hcryp->Instance->IVR1 = 0U; + hcryp->Instance->IVR0 = 0U; + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write the B0 packet into CRYP_DIN*/ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 3); + + /* wait until the end of computation */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked & return error */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* From that point the whole message must be processed, first the Header then the payload. + First the Header block(B1) : associated data length expressed in bytes concatenated with Associated Data (A)*/ + + if (hcryp->Init.HeaderSize != 0U) + { + if ((hcryp->Init.HeaderSize % 4U) == 0U) + { + /* HeaderSize %4, no padding */ + for (loopcounter = 0U; (loopcounter < hcryp->Init.HeaderSize); loopcounter += 4U) + { + /* Write the Input block in the Data Input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + else + { + /*Write Header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((hcryp->Init.HeaderSize) - (hcryp->Init.HeaderSize % 4U))); loopcounter += 4U) + { + /* Write the input block in the data input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; (loopcounter < (hcryp->Init.HeaderSize % 4U)); loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + } /* if (DoKeyIVConfig == 1U) */ + /* Then the payload: cleartext payload (not the ciphertext payload). + Write input Data, no output Data to get */ + if (hcryp->Size != 0U) + { + if ((hcryp->Size % 16U) != 0U) + { + /* recalculate wordsize */ + wordsize = ((wordsize / 4U) * 4U) ; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + while ((hcryp->CrypInCount < wordsize) && (outcount < wordsize)) + { + /* Write plain data and get cipher data */ + CRYP_AES_ProcessData(hcryp, Timeout); + + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + if ((hcryp->Size % 16U) != 0U) + { + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter ++) + { + /* Write the last input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0U; + loopcounter++; + } + /* Wait for CCF flag to be raised */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + } + } +#endif /* End AES or CRYP */ + +#if defined(CRYP) + + /************************* Header phase *************************************/ + /* Header block(B1) : associated data length expressed in bytes concatenated + with Associated Data (A)*/ + + if (CRYP_GCMCCM_SetHeaderPhase(hcryp, Timeout) != HAL_OK) + { + return HAL_ERROR; + } + + /********************** Payload phase ***************************************/ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Disable the CRYP peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + } /* if (DoKeyIVConfig == 1U) */ + + if ((hcryp->Size % 16U) != 0U) + { + /* recalculate wordsize */ + wordsize = ((wordsize / 4U) * 4U) ; + } + /* Get tick */ + tickstart = HAL_GetTick(); + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + /* Write input data and get output data */ + while ((hcryp->CrypInCount < wordsize) && (outcount < wordsize)) + { + /* Write plain data and get cipher data */ + CRYP_AES_ProcessData(hcryp, Timeout); + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + if ((hcryp->Size % 16U) != 0U) + { + /* CRYP Workaround : CRYP1 generates correct TAG during CCM decryption only when ciphertext blocks size is multiple of + 128 bits. If lthe size of the last block of payload is inferior to 128 bits, when CCM decryption + is selected, then the TAG message will be wrong.*/ + CRYP_Workaround(hcryp, Timeout); + } +#endif /* CRYP */ + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief AES CCM encryption/decryption process in interrupt mode + * for TinyAES IP, no encrypt/decrypt performed, only authentication preparation. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESCCM_Process_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ +#if defined(CRYP) + __IO uint32_t count = 0U; +#endif /* CRYP */ + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + /* Configure Key, IV and process message (header and payload) */ + if (DoKeyIVConfig == 1U) + { + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + +#if defined(CRYP) + + /************ Init phase ************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector (IV) with CTR1 information */ + hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0; + hcryp->Instance->IV0RR = hcryp->Init.B0[1]; + hcryp->Instance->IV1LR = hcryp->Init.B0[2]; + hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2; + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write the B0 packet into CRYP_DIN Register*/ + if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3); + } + /*Wait for the CRYPEN bit to be cleared*/ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + } /* end of if (DoKeyIVConfig == 1U) */ + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI); + + /* Enable CRYP */ + __HAL_CRYP_ENABLE(hcryp); + +#else /* AES */ + + /*AES2v1.1.1 : CCM authentication : no init phase, only header and final phase */ + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* configured mode and encryption mode */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector with zero values*/ + hcryp->Instance->IVR3 = 0U; + hcryp->Instance->IVR2 = 0U; + hcryp->Instance->IVR1 = 0U; + hcryp->Instance->IVR0 = 0U; + + /* Enable interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write the B0 packet into CRYP_DIN*/ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 3); + + } /* end of if (DoKeyIVConfig == 1U) */ +#endif /* End AES or CRYP */ + + /* Return function status */ + return HAL_OK; +} +/** + * @brief AES CCM encryption/decryption process in DMA mode + * for TinyAES IP, no encrypt/decrypt performed, only authentication preparation. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_AESCCM_Process_DMA(CRYP_HandleTypeDef *hcryp) +{ + uint32_t wordsize; + __IO uint32_t count = 0U; + uint32_t DoKeyIVConfig = 1U; /* By default, carry out peripheral Key and IV configuration */ +#if defined(AES) + uint32_t loopcounter; + uint32_t npblb; + uint32_t lastwordsize; +#endif + + if (hcryp->Init.KeyIVConfigSkip == CRYP_KEYIVCONFIG_ONCE) + { + if (hcryp->KeyIVConfig == 1U) + { + /* If the Key and IV configuration has to be done only once + and if it has already been done, skip it */ + DoKeyIVConfig = 0U; + hcryp->SizesSum += hcryp->Size; /* Compute message total payload length */ + } + else + { + /* If the Key and IV configuration has to be done only once + and if it has not been done already, do it and set KeyIVConfig + to keep track it won't have to be done again next time */ + hcryp->KeyIVConfig = 1U; + hcryp->SizesSum = hcryp->Size; /* Merely store payload length */ + } + } + else + { + hcryp->SizesSum = hcryp->Size; + } + + if (DoKeyIVConfig == 1U) + { + + /* Reset CrypHeaderCount */ + hcryp->CrypHeaderCount = 0U; + +#if defined(CRYP) + + /************************** Init phase **************************************/ + + CRYP_SET_PHASE(hcryp, CRYP_PHASE_INIT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector (IV) with CTR1 information */ + hcryp->Instance->IV0LR = (hcryp->Init.B0[0]) & CRYP_CCM_CTR1_0; + hcryp->Instance->IV0RR = hcryp->Init.B0[1]; + hcryp->Instance->IV1LR = hcryp->Init.B0[2]; + hcryp->Instance->IV1RR = (hcryp->Init.B0[3] & CRYP_CCM_CTR1_1) | CRYP_CCM_CTR1_2; + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write the B0 packet into CRYP_DIN Register*/ + if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __REV(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 1), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 2), 16); + hcryp->Instance->DIN = __ROR(*(uint32_t *)(hcryp->Init.B0 + 3), 16); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 1)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 2)); + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(hcryp->Init.B0 + 3)); + } + else + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.B0 + 3); + } + + /*Wait for the CRYPEN bit to be cleared*/ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while ((hcryp->Instance->CR & CRYP_CR_CRYPEN) == CRYP_CR_CRYPEN); + +#else /* AES */ + + /*AES2v1.1.1 : CCM authentication : no init phase, only header and final phase */ + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* configured encryption mode */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT); + + /* Set the key */ + CRYP_SetKey(hcryp, hcryp->Init.KeySize); + + /* Set the initialization vector with zero values*/ + hcryp->Instance->IVR3 = 0U; + hcryp->Instance->IVR2 = 0U; + hcryp->Instance->IVR1 = 0U; + hcryp->Instance->IVR0 = 0U; + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /*Write the B0 packet into CRYP_DIN*/ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 1); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 2); + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.B0 + 3); + + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* From that point the whole message must be processed, first the Header then the payload. + First the Header block(B1) : associated data length expressed in bytes concatenated with Associated Data (A)*/ + + if (hcryp->Init.HeaderSize != 0U) + { + if ((hcryp->Init.HeaderSize % 4U) == 0U) + { + /* HeaderSize %4, no padding */ + for (loopcounter = 0U; (loopcounter < hcryp->Init.HeaderSize); loopcounter += 4U) + { + /* Write the Input block in the Data Input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /* wait until the end of computation */ + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + else + { + /*Write Header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((hcryp->Init.HeaderSize) - (hcryp->Init.HeaderSize % 4U))); loopcounter += 4U) + { + /* Write the input block in the data input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; (loopcounter < (hcryp->Init.HeaderSize % 4U)); loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + } /* if (DoKeyIVConfig == 1U) */ + /* Then the payload: cleartext payload (not the ciphertext payload). + Write input Data, no output Data to get */ + if (hcryp->Size != 0U) + { + if (hcryp->Size >= 16U) + { + if ((hcryp->Size % 16U) == 0U) + { + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (hcryp->Size / 4U), (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + else /*to compute last word<128bits, otherwise it will not be encrypted/decrypted */ + { + wordsize = (uint32_t)(hcryp->Size) + (16U - ((uint32_t)(hcryp->Size) % 16U)) ; + + /* Set the input and output addresses and start DMA transfer, pCrypOutBuffPtr size should be %4 */ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), ((uint16_t)wordsize / 4U), + (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + } + if ((hcryp->Size < 16U) != 0U) + { + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter ++) + { + /* Write the last input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0U; + loopcounter++; + } + count = CRYP_TIMEOUT_GCMCCMINITPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state and phase */ + hcryp->State = HAL_CRYP_STATE_READY; + } + } + else + { + /* Process unLocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state and phase */ + hcryp->State = HAL_CRYP_STATE_READY; + } +#endif /* AES */ +#if defined(CRYP) + /********************* Header phase *****************************************/ + + if (CRYP_GCMCCM_SetHeaderPhase_DMA(hcryp) != HAL_OK) + { + return HAL_ERROR; + } + + /******************** Payload phase *****************************************/ + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Disable the CRYP peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + } /* if (DoKeyIVConfig == 1U) */ + if (hcryp->Size != 0U) + { + /* Size should be %4 otherwise Tag will be incorrectly generated for GCM Encryption & CCM Decryption + Workaround is implemented in polling mode, so if last block of + payload <128bit don't use HAL_CRYP_AESGCM_DMA otherwise TAG is incorrectly generated for GCM Encryption. */ + /* Set the input and output addresses and start DMA transfer */ + if ((hcryp->Size % 16U) == 0U) + { + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), hcryp->Size / 4U, (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + else + { + wordsize = (uint32_t)(hcryp->Size) + 16U - ((uint32_t)(hcryp->Size) % 16U) ; + + /* Set the input and output addresses and start DMA transfer, pCrypOutBuffPtr size should be %4*/ + CRYP_SetDMAConfig(hcryp, (uint32_t)(hcryp->pCrypInBuffPtr), (uint16_t)wordsize / 4U, + (uint32_t)(hcryp->pCrypOutBuffPtr)); + } + } + else /*Size = 0*/ + { + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state and phase */ + hcryp->State = HAL_CRYP_STATE_READY; + } +#endif /* CRYP */ + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Sets the payload phase in iterrupt mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @retval state + */ +static void CRYP_GCMCCM_SetPayloadPhase_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t loopcounter; + uint32_t temp[4]; /* Temporary CrypOutBuff */ + uint32_t lastwordsize; + uint32_t npblb; + uint32_t i; +#if defined(AES) + uint16_t outcount; /* Temporary CrypOutCount Value */ +#endif /* AES */ + + /***************************** Payload phase *******************************/ + +#if defined(CRYP) + if (hcryp->Size == 0U) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + } + + else if (((hcryp->Size / 4U) - (hcryp->CrypInCount)) >= 4U) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + if (((hcryp->Size / 4U) == hcryp->CrypInCount) && ((hcryp->Size % 16U) == 0U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI); + + /* Call the input data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + if (hcryp->CrypOutCount < (hcryp->Size / 4U)) + { + /* Read the output block from the Output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer */ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + i = 0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + if (((hcryp->Size / 4U) == hcryp->CrypOutCount) && ((hcryp->Size % 16U) == 0U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Call output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + } + else if ((hcryp->Size % 16U) != 0U) + { + /* Size should be %4 in word and %16 in byte otherwise TAG will be incorrectly generated for GCM Encryption & CCM Decryption + Workaround is implemented in polling mode, so if last block of + payload <128bit don't use CRYP_AESGCM_Encrypt_IT otherwise TAG is incorrectly generated. */ + + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter++) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DIN = 0x0U; + loopcounter++; + } + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI); + + if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) + { + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUT; + } + if (((hcryp->Size) / 4U) == 0U) + { + for (i = 0U; i < ((uint32_t)(hcryp->Size) % 4U); i++) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + } + } + i = 0x0U; + while (((hcryp->CrypOutCount < ((hcryp->Size) / 4U))) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + } + if (hcryp->CrypOutCount >= (hcryp->Size / 4U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_OUTI | CRYP_IT_INI); + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Call output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + else + { + /* Nothing to do */ + } +#else /* AES */ + + /* Read the output block from the output FIFO and put them in temporary buffer then get CrypOutBuff from temporary buffer*/ + for (i = 0U; i < 4U; i++) + { + temp[i] = hcryp->Instance->DOUTR; + } + i = 0U; + while ((hcryp->CrypOutCount < ((hcryp->Size + 3U) / 4U)) && (i < 4U)) + { + *(uint32_t *)(hcryp->pCrypOutBuffPtr + hcryp->CrypOutCount) = temp[i]; + hcryp->CrypOutCount++; + i++; + } + /*Temporary CrypOutCount Value*/ + outcount = hcryp->CrypOutCount; + + if ((hcryp->CrypOutCount >= (hcryp->Size / 4U)) && ((outcount * 4U) >= hcryp->Size)) + { + /* Disable computation complete flag and errors interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Call output transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Output complete callback*/ + hcryp->OutCpltCallback(hcryp); +#else + /*Call legacy weak Output complete callback*/ + HAL_CRYP_OutCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + else if (((hcryp->Size / 4U) - (hcryp->CrypInCount)) >= 4U) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + if ((hcryp->CrypInCount == (hcryp->Size / 4U)) && ((hcryp->Size % 16U) == 0U)) + { + /* Call Input transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + else /* Last block of payload < 128bit*/ + { + /* Workaround not implemented, Size should be %4 otherwise Tag will be incorrectly + generated for GCM Encryption & CCM Decryption. Workaround is implemented in polling mode, so if last block of + payload <128bit don't use CRYP_Encrypt_IT otherwise TAG is incorrectly generated for GCM Encryption & CCM Decryption. */ + + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } +#endif /* AES */ + +} + + +/** + * @brief Sets the header phase in polling mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module(Header & HeaderSize) + * @param Timeout: Timeout value + * @retval state + */ +static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t loopcounter; + uint32_t size_in_bytes; + uint32_t tmp; + uint32_t mask[12] = {0x0U, 0xFF000000U, 0xFFFF0000U, 0xFFFFFF00U, /* 32-bit data type */ + 0x0U, 0x0000FF00U, 0x0000FFFFU, 0xFF00FFFFU, /* 16-bit data type */ + 0x0U, 0x000000FFU, 0x0000FFFFU, 0x00FFFFFFU}; /* 8-bit data type */ + + /***************************** Header phase for GCM/GMAC or CCM *********************************/ + + if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_WORD) + { + size_in_bytes = hcryp->Init.HeaderSize * 4U; + } + else + { + size_in_bytes = hcryp->Init.HeaderSize; + } + + if (size_in_bytes != 0U) + { + +#if defined(CRYP) + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + if ((size_in_bytes % 16U) == 0U) + { + /* HeaderSize %4, no padding */ + for (loopcounter = 0U; (loopcounter < (size_in_bytes / 4U)); loopcounter += 4U) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /* Wait for IFEM to be raised */ + if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + else + { + /*Write header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((size_in_bytes / 16U) * 4U)); loopcounter += 4U) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /* Wait for IFEM to be raised */ + if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; (loopcounter < ((size_in_bytes / 4U) % 4U)); loopcounter++) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + /* If the header size is a multiple of words */ + if ((size_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + } + } + else + { + /* Enter last bytes, padded with zeroes */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (size_in_bytes % 4U)]; + hcryp->Instance->DIN = tmp; + loopcounter++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + } + } + /* Wait for CCF IFEM to be raised */ + if (CRYP_WaitOnIFEMFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + /* Wait until the complete message has been processed */ + if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked & return error */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + +#else /* AES */ + + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + /* Workaround 1 :only AES before re-enabling the IP, datatype can be configured.*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, hcryp->Init.DataType); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + } + /* If size_in_bytes is a multiple of blocks (a multiple of four 32-bits words ) */ + if ((size_in_bytes % 16U) == 0U) + { + /* No padding */ + for (loopcounter = 0U; (loopcounter < (size_in_bytes / 4U)); loopcounter += 4U) + { + /* Write the input block in the data input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + else + { + /*Write header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((size_in_bytes / 16U) * 4U)); loopcounter += 4U) + { + /* Write the input block in the data input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + /* Write last complete words */ + for (loopcounter = 0U; (loopcounter < ((size_in_bytes / 4U) % 4U)); loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + /* If the header size is a multiple of words */ + if ((size_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + else + { + /* Enter last bytes, padded with zeroes */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (size_in_bytes % 4U)]; + hcryp->Instance->DINR = tmp; + loopcounter++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } +#endif /* End AES or CRYP */ + } + else + { +#if defined(AES) + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + /*Workaround 1: only AES, before re-enabling the IP, datatype can be configured.*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, hcryp->Init.DataType); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + } +#endif /* AES */ + } + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Sets the header phase when using DMA in process + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module(Header & HeaderSize) + * @retval None + */ +static HAL_StatusTypeDef CRYP_GCMCCM_SetHeaderPhase_DMA(CRYP_HandleTypeDef *hcryp) +{ + __IO uint32_t count = 0U; + uint32_t loopcounter; + uint32_t headersize_in_bytes; + uint32_t tmp; + uint32_t mask[12] = {0x0U, 0xFF000000U, 0xFFFF0000U, 0xFFFFFF00U, /* 32-bit data type */ + 0x0U, 0x0000FF00U, 0x0000FFFFU, 0xFF00FFFFU, /* 16-bit data type */ + 0x0U, 0x000000FFU, 0x0000FFFFU, 0x00FFFFFFU}; /* 8-bit data type */ + + /***************************** Header phase for GCM/GMAC or CCM *********************************/ + if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_WORD) + { + headersize_in_bytes = hcryp->Init.HeaderSize * 4U; + } + else + { + headersize_in_bytes = hcryp->Init.HeaderSize; + } + + if (headersize_in_bytes != 0U) + { + +#if defined(CRYP) + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + if ((headersize_in_bytes % 16U) == 0U) + { + /* HeaderSize %4, no padding */ + for (loopcounter = 0U; (loopcounter < (headersize_in_bytes / 4U)); loopcounter += 4U) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /* Wait for IFEM to be raised */ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM)); + } + } + else + { + /*Write header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((headersize_in_bytes / 16U) * 4U)); loopcounter += 4U) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /* Wait for IFEM to be raised */ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM)); + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; (loopcounter < ((headersize_in_bytes / 4U) % 4U)); loopcounter++) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + /* If the header size is a multiple of words */ + if ((headersize_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + } + } + else + { + /* Enter last bytes, padded with zeroes */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (headersize_in_bytes % 4U)]; + hcryp->Instance->DIN = tmp; + loopcounter++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + } + } + /* Wait for IFEM to be raised */ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM)); + } + /* Wait until the complete message has been processed */ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY)); + +#else /* AES */ + + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + /* Workaround 1: only AES, before re-enabling the IP, datatype can be configured.*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, hcryp->Init.DataType); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + } + if ((headersize_in_bytes % 16U) == 0U) + { + /* HeaderSize %4, no padding */ + for (loopcounter = 0U; (loopcounter < (headersize_in_bytes / 4U)); loopcounter += 4U) + { + /* Write the input block in the data input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /*Wait on CCF flag*/ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + } + else + { + /*Write header block in the IN FIFO without last block */ + for (loopcounter = 0U; (loopcounter < ((headersize_in_bytes / 16U) * 4U)); loopcounter += 4U) + { + /* Write the Input block in the Data Input register */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + + /*Wait on CCF flag*/ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; (loopcounter < ((headersize_in_bytes / 4U) % 4U)); loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + /* If the header size is a multiple of words */ + if ((headersize_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + else + { + /* Enter last bytes, padded with zeroes */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (headersize_in_bytes % 4U)]; + hcryp->Instance->DINR = tmp; + loopcounter++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + /*Wait on CCF flag*/ + count = CRYP_TIMEOUT_GCMCCMHEADERPHASE; + do + { + count-- ; + if (count == 0U) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)); + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + } +#endif /* End AES or CRYP */ + } + else + { +#if defined(AES) + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + /*Workaround 1: only AES, before re-enabling the IP, datatype can be configured.*/ + MODIFY_REG(hcryp->Instance->CR, AES_CR_DATATYPE, hcryp->Init.DataType); + + /* Select header phase */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_HEADER); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + } +#endif /* AES */ + } + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Sets the header phase in interrupt mode + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module(Header & HeaderSize) + * @retval None + */ +static void CRYP_GCMCCM_SetHeaderPhase_IT(CRYP_HandleTypeDef *hcryp) +{ + uint32_t loopcounter; +#if defined(AES) + uint32_t lastwordsize; + uint32_t npblb; +#endif + uint32_t headersize_in_bytes; + uint32_t tmp; + uint32_t mask[12] = {0x0U, 0xFF000000U, 0xFFFF0000U, 0xFFFFFF00U, /* 32-bit data type */ + 0x0U, 0x0000FF00U, 0x0000FFFFU, 0xFF00FFFFU, /* 16-bit data type */ + 0x0U, 0x000000FFU, 0x0000FFFFU, 0x00FFFFFFU}; /* 8-bit data type */ + + if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_WORD) + { + headersize_in_bytes = hcryp->Init.HeaderSize * 4U; + } + else + { + headersize_in_bytes = hcryp->Init.HeaderSize; + } + + /***************************** Header phase *********************************/ + +#if defined(CRYP) + if (headersize_in_bytes <= ((uint32_t)(hcryp->CrypHeaderCount) * 4U)) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_INI); + + /* Disable the CRYP peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Select payload phase once the header phase is performed */ + CRYP_SET_PHASE(hcryp, CRYP_PHASE_PAYLOAD); + + /* Enable Interrupts */ + __HAL_CRYP_ENABLE_IT(hcryp, CRYP_IT_INI | CRYP_IT_OUTI); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + } + else if (((headersize_in_bytes / 4U) - (hcryp->CrypHeaderCount)) >= 4U) + + { + /* HeaderSize %4, no padding */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + else + { + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < ((headersize_in_bytes / 4U) % 4U); loopcounter++) + { + hcryp->Instance->DIN = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + if ((headersize_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + hcryp->CrypHeaderCount++; + } + } + else + { + /* Enter last bytes, padded with zeros */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (headersize_in_bytes % 4U)]; + hcryp->Instance->DIN = tmp; + loopcounter++; + hcryp->CrypHeaderCount++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DIN = 0x0U; + loopcounter++; + hcryp->CrypHeaderCount++; + } + } + } +#else /* AES */ + + if (headersize_in_bytes <= ((uint32_t)(hcryp->CrypHeaderCount) * 4U)) + { + /* Set the phase */ + hcryp->Phase = CRYP_PHASE_PROCESS; + + /* Payload phase not supported in CCM AES2 */ + if (hcryp->Init.Algorithm == CRYP_AES_GCM_GMAC) + { + /* Select payload phase once the header phase is performed */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_PAYLOAD); + } + if (hcryp->Init.Algorithm == CRYP_AES_CCM) + { + /* Increment CrypHeaderCount to pass in CRYP_GCMCCM_SetPayloadPhase_IT */ + hcryp->CrypHeaderCount++; + } + /* Write the payload Input block in the IN FIFO */ + if (hcryp->Size == 0U) + { + /* Disable interrupts */ + __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE); + + /* Change the CRYP state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + else if (hcryp->Size >= 16U) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + + if ((hcryp->CrypInCount == (hcryp->Size / 4U)) && ((hcryp->Size % 16U) == 0U)) + { + /* Call the input data transfer complete callback */ +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered Input complete callback*/ + hcryp->InCpltCallback(hcryp); +#else + /*Call legacy weak Input complete callback*/ + HAL_CRYP_InCpltCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + else /* Size < 4 words : first block is the last block*/ + { + /* Workaround not implemented, Size should be %4 otherwise Tag will be incorrectly + generated for GCM Encryption. Workaround is implemented in polling mode, so if last block of + payload <128bit don't use CRYP_Encrypt_IT otherwise TAG is incorrectly generated for GCM Encryption. */ + + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < lastwordsize; loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (loopcounter < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0x0U; + loopcounter++; + } + } + } + else if (((headersize_in_bytes / 4U) - (hcryp->CrypHeaderCount)) >= 4U) + { + /* Write the input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++; + } + else /*HeaderSize < 4 or HeaderSize >4 & HeaderSize %4 != 0*/ + { + /* Last block optionally pad the data with zeros*/ + for (loopcounter = 0U; loopcounter < ((headersize_in_bytes / 4U) % 4U); loopcounter++) + { + hcryp->Instance->DINR = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + hcryp->CrypHeaderCount++ ; + } + /* If the header size is a multiple of words */ + if ((headersize_in_bytes % 4U) == 0U) + { + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + hcryp->CrypHeaderCount++; + } + } + else + { + /* Enter last bytes, padded with zeros */ + tmp = *(uint32_t *)(hcryp->Init.Header + hcryp->CrypHeaderCount); + tmp &= mask[(hcryp->Init.DataType * 2U) + (headersize_in_bytes % 4U)]; + hcryp->Instance->DINR = tmp; + loopcounter++; + hcryp->CrypHeaderCount++; + /* Pad the data with zeros to have a complete block */ + while (loopcounter < 4U) + { + hcryp->Instance->DINR = 0x0U; + loopcounter++; + hcryp->CrypHeaderCount++; + } + } + } +#endif /* End AES or CRYP */ +} + + +/** + * @brief Workaround used for GCM/CCM mode. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param Timeout: specify Timeout value + * @retval None + */ +static void CRYP_Workaround(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t lastwordsize; + uint32_t npblb; +#if defined(CRYP) + uint32_t iv1temp; + uint32_t temp[4] = {0}; + uint32_t temp2[4] = {0}; +#endif /* CRYP */ + uint32_t intermediate_data[4] = {0}; + uint32_t index; + + /* Compute the number of padding bytes in last block of payload */ + npblb = ((((uint32_t)(hcryp->Size) / 16U) + 1U) * 16U) - (uint32_t)(hcryp->Size); + + /* Number of valid words (lastwordsize) in last block */ + if ((npblb % 4U) == 0U) + { + lastwordsize = (16U - npblb) / 4U; + } + else + { + lastwordsize = ((16U - npblb) / 4U) + 1U; + } + +#if defined(CRYP) + + /* Workaround 2, case GCM encryption */ + if (hcryp->Init.Algorithm == CRYP_AES_GCM) + { + if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT) + { + /*Workaround in order to properly compute authentication tags while doing + a GCM encryption with the last block of payload size inferior to 128 bits*/ + /* Disable CRYP to start the final phase */ + __HAL_CRYP_DISABLE(hcryp); + + /*Update CRYP_IV1R register and ALGOMODE*/ + hcryp->Instance->IV1RR = ((hcryp->Instance->CSGCMCCM7R) - 1U); + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CTR); + + /* Enable CRYP to start the final phase */ + __HAL_CRYP_ENABLE(hcryp); + } + /* Last block optionally pad the data with zeros*/ + for (index = 0; index < lastwordsize; index ++) + { + /* Write the last input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (index < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DIN = 0U; + index++; + } + /* Wait for OFNE flag to be raised */ + if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) + { + for (index = 0U; index < 4U; index++) + { + /* Read the output block from the output FIFO */ + intermediate_data[index] = hcryp->Instance->DOUT; + + /* Intermediate data buffer to be used in for the workaround*/ + *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = intermediate_data[index]; + hcryp->CrypOutCount++; + } + } + + if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_ENCRYPT) + { + /*workaround in order to properly compute authentication tags while doing + a GCM encryption with the last block of payload size inferior to 128 bits*/ + /* Change the AES mode to GCM mode and Select Final phase */ + /* configured CHMOD GCM */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_GCM); + + /* configured final phase */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL); + + if ((hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_32B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFFFF00U; + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFF0000U; + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= 0xFF000000U; + } + } + else if ((hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_8B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFFFFFF00U); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFFFF0000U); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFF000000U); + } + } + else if ((hcryp->Instance->CR & CRYP_CR_DATATYPE) == CRYP_DATATYPE_16B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFFFFFF00U), 16); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFFFF0000U), 16); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFF000000U), 16); + } + } + else /*CRYP_DATATYPE_1B*/ + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFFFFFF00U); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFFFF0000U); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFF000000U); + } + } + for (index = 0U; index < lastwordsize; index ++) + { + /*Write the intermediate_data in the IN FIFO */ + hcryp->Instance->DIN = intermediate_data[index]; + } + while (index < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DIN = 0x0U; + index++; + } + /* Wait for OFNE flag to be raised */ + if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) + { + for (index = 0U; index < 4U; index++) + { + intermediate_data[index] = hcryp->Instance->DOUT; + } + } + } + } /* End of GCM encryption */ + else + { + /* Workaround 2, case CCM decryption, in order to properly compute + authentication tags while doing a CCM decryption with the last block + of payload size inferior to 128 bits*/ + + if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT) + { + iv1temp = hcryp->Instance->CSGCMCCM7R; + + /* Disable CRYP to start the final phase */ + __HAL_CRYP_DISABLE(hcryp); + + temp[0] = hcryp->Instance->CSGCMCCM0R; + temp[1] = hcryp->Instance->CSGCMCCM1R; + temp[2] = hcryp->Instance->CSGCMCCM2R; + temp[3] = hcryp->Instance->CSGCMCCM3R; + + hcryp->Instance->IV1RR = iv1temp; + + /* Configured CHMOD CTR */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CTR); + + /* Enable CRYP to start the final phase */ + __HAL_CRYP_ENABLE(hcryp); + } + /* Last block optionally pad the data with zeros*/ + for (index = 0; index < lastwordsize; index ++) + { + /* Write the last Input block in the IN FIFO */ + hcryp->Instance->DIN = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (index < 4U) + { + /* Pad the data with zeros to have a complete block */ + hcryp->Instance->DIN = 0U; + index++; + } + /* Wait for OFNE flag to be raised */ + if (CRYP_WaitOnOFNEFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + if ((hcryp->Instance->SR & CRYP_FLAG_OFNE) != 0x0U) + { + for (index = 0U; index < 4U; index++) + { + /* Read the Output block from the Output FIFO */ + intermediate_data[index] = hcryp->Instance->DOUT; + + /*intermediate data buffer to be used in for the workaround*/ + *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = intermediate_data[index]; + hcryp->CrypOutCount++; + } + } + + if ((hcryp->Instance->CR & CRYP_CR_ALGODIR) == CRYP_OPERATINGMODE_DECRYPT) + { + temp2[0] = hcryp->Instance->CSGCMCCM0R; + temp2[1] = hcryp->Instance->CSGCMCCM1R; + temp2[2] = hcryp->Instance->CSGCMCCM2R; + temp2[3] = hcryp->Instance->CSGCMCCM3R; + + /* configured CHMOD CCM */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_ALGOMODE, CRYP_AES_CCM); + + /* configured Header phase */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_HEADER); + + /*set to zero the bits corresponding to the padded bits*/ + for (index = lastwordsize; index < 4U; index ++) + { + intermediate_data[index] = 0U; + } + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFFFF00U; + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFF0000U; + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= 0xFF000000U; + } + for (index = 0U; index < 4U ; index ++) + { + intermediate_data[index] ^= temp[index]; + intermediate_data[index] ^= temp2[index]; + } + for (index = 0U; index < 4U; index ++) + { + /* Write the last Input block in the IN FIFO */ + hcryp->Instance->DIN = intermediate_data[index] ; + } + + /* Wait for BUSY flag to be raised */ + if (CRYP_WaitOnBUSYFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + } + } /* End of CCM WKA*/ + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); + +#else /* AES */ + + /*Workaround 2: case GCM encryption, during payload phase and before inserting + the last block of paylaod, which size is inferior to 128 bits */ + + if ((hcryp->Instance->CR & AES_CR_MODE) == CRYP_OPERATINGMODE_ENCRYPT) + { + /* configured CHMOD CTR */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_CHMOD, CRYP_AES_CTR); + } + /* last block optionally pad the data with zeros*/ + for (index = 0U; index < lastwordsize; index ++) + { + /* Write the last Input block in the IN FIFO */ + hcryp->Instance->DINR = *(uint32_t *)(hcryp->pCrypInBuffPtr + hcryp->CrypInCount); + hcryp->CrypInCount++; + } + while (index < 4U) + { + /* pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0U; + index++; + } + /* Wait for CCF flag to be raised */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + hcryp->State = HAL_CRYP_STATE_READY; + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + for (index = 0U; index < 4U; index++) + { + /* Read the Output block from the Output FIFO */ + intermediate_data[index] = hcryp->Instance->DOUTR; + + /*intermediate data buffer to be used in the workaround*/ + *(uint32_t *)(hcryp->pCrypOutBuffPtr + (hcryp->CrypOutCount)) = intermediate_data[index]; + hcryp->CrypOutCount++; + } + + if ((hcryp->Instance->CR & AES_CR_MODE) == CRYP_OPERATINGMODE_ENCRYPT) + { + /* configured CHMOD GCM */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_CHMOD, CRYP_AES_GCM_GMAC); + + /* Select final phase */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_FINAL); + + if ((hcryp->Instance->CR & AES_CR_DATATYPE) == CRYP_DATATYPE_32B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFFFF00U; + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= 0xFFFF0000U; + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= 0xFF000000U; + } + } + else if ((hcryp->Instance->CR & AES_CR_DATATYPE) == CRYP_DATATYPE_8B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFFFFFF00U); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFFFF0000U); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __REV(0xFF000000U); + } + } + else if ((hcryp->Instance->CR & AES_CR_DATATYPE) == CRYP_DATATYPE_16B) + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFFFFFF00U), 16); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFFFF0000U), 16); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __ROR((0xFF000000U), 16); + } + } + else /*CRYP_DATATYPE_1B*/ + { + if ((npblb % 4U) == 1U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFFFFFF00U); + } + if ((npblb % 4U) == 2U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFFFF0000U); + } + if ((npblb % 4U) == 3U) + { + intermediate_data[lastwordsize - 1U] &= __RBIT(0xFF000000U); + } + } + + /*Write the intermediate_data in the IN FIFO */ + for (index = 0U; index < lastwordsize; index ++) + { + hcryp->Instance->DINR = intermediate_data[index]; + } + while (index < 4U) + { + /* pad the data with zeros to have a complete block */ + hcryp->Instance->DINR = 0U; + index++; + } + /* Wait for CCF flag to be raised */ + if (CRYP_WaitOnCCFlag(hcryp, Timeout) != HAL_OK) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hcryp); +#if (USE_HAL_CRYP_REGISTER_CALLBACKS == 1U) + /*Call registered error callback*/ + hcryp->ErrorCallback(hcryp); +#else + /*Call legacy weak error callback*/ + HAL_CRYP_ErrorCallback(hcryp); +#endif /* USE_HAL_CRYP_REGISTER_CALLBACKS */ + } + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + + for (index = 0U; index < 4U; index++) + { + intermediate_data[index] = hcryp->Instance->DOUTR; + } + }/*End of Workaround 2*/ +#endif /* End AES or CRYP */ +} +#endif /* AES or GCM CCM defined*/ +#if defined (CRYP) +#if defined (CRYP_CR_ALGOMODE_AES_GCM) +/** + * @brief Handle CRYP hardware block Timeout when waiting for IFEM flag to be raised. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_WaitOnIFEMFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_IFEM)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_ERROR; + } + } + } + return HAL_OK; +} +#endif /* GCM CCM defined*/ +/** + * @brief Handle CRYP hardware block Timeout when waiting for BUSY flag to be raised. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_WaitOnBUSYFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + while (HAL_IS_BIT_SET(hcryp->Instance->SR, CRYP_FLAG_BUSY)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_ERROR; + } + } + } + return HAL_OK; +} + + +/** + * @brief Handle CRYP hardware block Timeout when waiting for OFNE flag to be raised. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_WaitOnOFNEFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +#else /* AES */ + +/** + * @brief Handle CRYP hardware block Timeout when waiting for CCF flag to be raised. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module. + * @param Timeout: Timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef CRYP_WaitOnCCFlag(CRYP_HandleTypeDef *hcryp, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Get timeout */ + tickstart = HAL_GetTick(); + + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +#endif /* End AES or CRYP */ + + +/** + * @} + */ + + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_CRYP_MODULE_ENABLED */ + + +/** + * @} + */ +#endif /* TinyAES or CRYP*/ +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c new file mode 100644 index 0000000..3a82847 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_cryp_ex.c @@ -0,0 +1,680 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_cryp_ex.c + * @author MCD Application Team + * @brief Extended CRYP HAL module driver + * This file provides firmware functions to manage the following + * functionalities of CRYP extension peripheral: + * + Extended AES processing 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 CRYP extension HAL driver can be used as follows: + (#)After AES-GCM or AES-CCM Encryption/Decryption user can start following API + to get the authentication messages : + (##) HAL_CRYPEx_AESGCM_GenerateAuthTAG + (##) HAL_CRYPEx_AESCCM_GenerateAuthTAG + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (AES) || defined (CRYP) +#if defined (CRYP_CR_ALGOMODE_AES_GCM)|| defined (AES) +/** @defgroup CRYPEx CRYPEx + * @brief CRYP Extension HAL module driver. + * @{ + */ + + +#ifdef HAL_CRYP_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup CRYPEx_Private_Defines + * @{ + */ +#if defined(AES) +#define CRYP_PHASE_INIT 0x00000000U /*!< GCM/GMAC (or CCM) init phase */ +#define CRYP_PHASE_HEADER AES_CR_GCMPH_0 /*!< GCM/GMAC or CCM header phase */ +#define CRYP_PHASE_PAYLOAD AES_CR_GCMPH_1 /*!< GCM(/CCM) payload phase */ +#define CRYP_PHASE_FINAL AES_CR_GCMPH /*!< GCM/GMAC or CCM final phase */ + +#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U /*!< Encryption mode */ +#define CRYP_OPERATINGMODE_KEYDERIVATION AES_CR_MODE_0 /*!< Key derivation mode only used when performing ECB and CBC decryptions */ +#define CRYP_OPERATINGMODE_DECRYPT AES_CR_MODE_1 /*!< Decryption */ +#define CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT AES_CR_MODE /*!< Key derivation and decryption only used when performing ECB and CBC decryptions */ + +#else /* CRYP */ + +#define CRYP_PHASE_INIT 0x00000000U +#define CRYP_PHASE_HEADER CRYP_CR_GCM_CCMPH_0 +#define CRYP_PHASE_PAYLOAD CRYP_CR_GCM_CCMPH_1 +#define CRYP_PHASE_FINAL CRYP_CR_GCM_CCMPH + +#define CRYP_OPERATINGMODE_ENCRYPT 0x00000000U +#define CRYP_OPERATINGMODE_DECRYPT CRYP_CR_ALGODIR +#endif /* End AES or CRYP */ + +#define CRYPEx_PHASE_PROCESS 0x02U /*!< CRYP peripheral is in processing phase */ +#define CRYPEx_PHASE_FINAL 0x03U /*!< CRYP peripheral is in final phase this is relevant only with CCM and GCM modes */ + +/* CTR0 information to use in CCM algorithm */ +#define CRYP_CCM_CTR0_0 0x07FFFFFFU +#define CRYP_CCM_CTR0_3 0xFFFFFF00U + + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + + + +/* Exported functions---------------------------------------------------------*/ +/** @addtogroup CRYPEx_Exported_Functions + * @{ + */ + +/** @defgroup CRYPEx_Exported_Functions_Group1 Extended AES processing functions + * @brief Extended processing functions. + * +@verbatim + ============================================================================== + ##### Extended AES processing functions ##### + ============================================================================== + [..] This section provides functions allowing to generate the authentication + TAG in Polling mode + (#)HAL_CRYPEx_AESGCM_GenerateAuthTAG + (#)HAL_CRYPEx_AESCCM_GenerateAuthTAG + they should be used after Encrypt/Decrypt operation. + +@endverbatim + * @{ + */ + + +/** + * @brief generate the GCM authentication TAG. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param AuthTag: Pointer to the authentication buffer + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout) +{ + uint32_t tickstart; + /* Assume first Init.HeaderSize is in words */ + uint64_t headerlength = (uint64_t)(hcryp->Init.HeaderSize) * 32U; /* Header length in bits */ + uint64_t inputlength = (uint64_t)hcryp->SizesSum * 8U; /* Input length in bits */ + uint32_t tagaddr = (uint32_t)AuthTag; + + /* Correct headerlength if Init.HeaderSize is actually in bytes */ + if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_BYTE) + { + headerlength /= 4U; + } + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Check if initialization phase has already been performed */ + if (hcryp->Phase == CRYPEx_PHASE_PROCESS) + { + /* Change the CRYP phase */ + hcryp->Phase = CRYPEx_PHASE_FINAL; + } + else /* Initialization phase has not been performed*/ + { + /* Disable the Peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Sequence error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE; + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + +#if defined(CRYP) + + /* Disable CRYP to start the final phase */ + __HAL_CRYP_DISABLE(hcryp); + + /* Select final phase */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL); + + /*ALGODIR bit must be set to '0'.*/ + hcryp->Instance->CR &= ~CRYP_CR_ALGODIR; + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* Write the number of bits in header (64 bits) followed by the number of bits + in the payload */ + if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __RBIT((uint32_t)(headerlength)); + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __RBIT((uint32_t)(inputlength)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __REV((uint32_t)(headerlength)); + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __REV((uint32_t)(inputlength)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __ROR((uint32_t)headerlength, 16U); + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = __ROR((uint32_t)inputlength, 16U); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_32B) + { + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = (uint32_t)(headerlength); + hcryp->Instance->DIN = 0U; + hcryp->Instance->DIN = (uint32_t)(inputlength); + } + else + { + /* Nothing to do */ + } + + /* Wait for OFNE flag to be raised */ + tickstart = HAL_GetTick(); + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP Peripheral Clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + /* Read the authentication TAG in the output FIFO */ + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + +#else /* AES*/ + + /* Select final phase */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_FINAL); + + /* Write the number of bits in header (64 bits) followed by the number of bits + in the payload */ + if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __RBIT((uint32_t)(headerlength)); + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __RBIT((uint32_t)(inputlength)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __REV((uint32_t)(headerlength)); + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __REV((uint32_t)(inputlength)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __ROR((uint32_t)headerlength, 16U); + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = __ROR((uint32_t)inputlength, 16U); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_32B) + { + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = (uint32_t)(headerlength); + hcryp->Instance->DINR = 0U; + hcryp->Instance->DINR = (uint32_t)(inputlength); + } + else + { + /* Nothing to do */ + } + /* Wait for CCF flag to be raised */ + tickstart = HAL_GetTick(); + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + /* Read the authentication TAG in the output FIFO */ + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + + /* Clear CCF flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* End AES or CRYP */ + + /* Disable the peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + } + else + { + /* Busy error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } + /* Return function status */ + return HAL_OK; +} + +/** + * @brief AES CCM Authentication TAG generation. + * @param hcryp: pointer to a CRYP_HandleTypeDef structure that contains + * the configuration information for CRYP module + * @param AuthTag: Pointer to the authentication buffer + * @param Timeout: Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout) +{ + uint32_t tagaddr = (uint32_t)AuthTag; + uint32_t ctr0 [4] = {0}; + uint32_t ctr0addr = (uint32_t)ctr0; + uint32_t tickstart; + + if (hcryp->State == HAL_CRYP_STATE_READY) + { + /* Process locked */ + __HAL_LOCK(hcryp); + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_BUSY; + + /* Check if initialization phase has already been performed */ + if (hcryp->Phase == CRYPEx_PHASE_PROCESS) + { + /* Change the CRYP phase */ + hcryp->Phase = CRYPEx_PHASE_FINAL; + } + else /* Initialization phase has not been performed*/ + { + /* Disable the peripheral */ + __HAL_CRYP_DISABLE(hcryp); + + /* Sequence error code field */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE; + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + +#if defined(CRYP) + + /* Disable CRYP to start the final phase */ + __HAL_CRYP_DISABLE(hcryp); + + /* Select final phase & ALGODIR bit must be set to '0'. */ + MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH | CRYP_CR_ALGODIR, CRYP_PHASE_FINAL | CRYP_OPERATINGMODE_ENCRYPT); + + /* Enable the CRYP peripheral */ + __HAL_CRYP_ENABLE(hcryp); + + /* Write the counter block in the IN FIFO, CTR0 information from B0 + data has to be swapped according to the DATATYPE*/ + ctr0[0] = (hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0; + ctr0[1] = hcryp->Init.B0[1]; + ctr0[2] = hcryp->Init.B0[2]; + ctr0[3] = hcryp->Init.B0[3] & CRYP_CCM_CTR0_3; + + if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr)); + } + else + { + hcryp->Instance->DIN = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DIN = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DIN = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DIN = *(uint32_t *)(ctr0addr); + } + /* Wait for OFNE flag to be raised */ + tickstart = HAL_GetTick(); + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral Clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + /* Read the Auth TAG in the IN FIFO */ + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT; + +#else /* AES */ + + /* Select final phase */ + MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_FINAL); + + /* Write the counter block in the IN FIFO, CTR0 information from B0 + data has to be swapped according to the DATATYPE*/ + if (hcryp->Init.DataType == CRYP_DATATYPE_8B) + { + ctr0[0] = (__REV(hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0); + ctr0[1] = __REV(hcryp->Init.B0[1]); + ctr0[2] = __REV(hcryp->Init.B0[2]); + ctr0[3] = (__REV(hcryp->Init.B0[3])& CRYP_CCM_CTR0_3); + + hcryp->Instance->DINR = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __REV(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __REV(*(uint32_t *)(ctr0addr)); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_16B) + { + ctr0[0] = (__ROR((hcryp->Init.B0[0]), 16U)& CRYP_CCM_CTR0_0); + ctr0[1] = __ROR((hcryp->Init.B0[1]), 16U); + ctr0[2] = __ROR((hcryp->Init.B0[2]), 16U); + ctr0[3] = (__ROR((hcryp->Init.B0[3]), 16U)& CRYP_CCM_CTR0_3); + + hcryp->Instance->DINR = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DINR = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DINR = __ROR(*(uint32_t *)(ctr0addr), 16U); + ctr0addr += 4U; + hcryp->Instance->DINR = __ROR(*(uint32_t *)(ctr0addr), 16U); + } + else if (hcryp->Init.DataType == CRYP_DATATYPE_1B) + { + ctr0[0] = (__RBIT(hcryp->Init.B0[0])& CRYP_CCM_CTR0_0); + ctr0[1] = __RBIT(hcryp->Init.B0[1]); + ctr0[2] = __RBIT(hcryp->Init.B0[2]); + ctr0[3] = (__RBIT(hcryp->Init.B0[3])& CRYP_CCM_CTR0_3); + + hcryp->Instance->DINR = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __RBIT(*(uint32_t *)(ctr0addr)); + ctr0addr += 4U; + hcryp->Instance->DINR = __RBIT(*(uint32_t *)(ctr0addr)); + } + else + { + ctr0[0] = (hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0; + ctr0[1] = hcryp->Init.B0[1]; + ctr0[2] = hcryp->Init.B0[2]; + ctr0[3] = hcryp->Init.B0[3] & CRYP_CCM_CTR0_3; + + hcryp->Instance->DINR = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DINR = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DINR = *(uint32_t *)(ctr0addr); + ctr0addr += 4U; + hcryp->Instance->DINR = *(uint32_t *)(ctr0addr); + } + + /* Wait for CCF flag to be raised */ + tickstart = HAL_GetTick(); + while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable the CRYP peripheral Clock */ + __HAL_CRYP_DISABLE(hcryp); + + /* Change state */ + hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT; + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + return HAL_ERROR; + } + } + } + + /* Read the authentication TAG in the output FIFO */ + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + tagaddr += 4U; + *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR; + + /* Clear CCF Flag */ + __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR); + +#endif /* End of AES || CRYP */ + + /* Change the CRYP peripheral state */ + hcryp->State = HAL_CRYP_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hcryp); + + /* Disable CRYP */ + __HAL_CRYP_DISABLE(hcryp); + } + else + { + /* Busy error code field */ + hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY; + return HAL_ERROR; + } + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +#if defined (AES) +/** @defgroup CRYPEx_Exported_Functions_Group2 Key Derivation functions + * @brief AutoKeyDerivation functions + * +@verbatim + ============================================================================== + ##### Key Derivation functions ##### + ============================================================================== + [..] This section provides functions allowing to Enable or Disable the + the AutoKeyDerivation parameter in CRYP_HandleTypeDef structure + These function are allowed only in TinyAES IP. + +@endverbatim + * @{ + */ + +/** + * @brief AES enable key derivation functions + * @param hcryp: pointer to a CRYP_HandleTypeDef structure. + * @retval None + */ +void HAL_CRYPEx_EnableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp) +{ + if (hcryp->State == HAL_CRYP_STATE_READY) + { + hcryp->AutoKeyDerivation = ENABLE; + } + else + { + /* Busy error code field */ + hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY; + } +} +/** + * @brief AES disable key derivation functions + * @param hcryp: pointer to a CRYP_HandleTypeDef structure. + * @retval None + */ +void HAL_CRYPEx_DisableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp) +{ + if (hcryp->State == HAL_CRYP_STATE_READY) + { + hcryp->AutoKeyDerivation = DISABLE; + } + else + { + /* Busy error code field */ + hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY; + } +} + +/** + * @} + */ +#endif /* AES or GCM CCM defined*/ +#endif /* AES */ +#endif /* HAL_CRYP_MODULE_ENABLED */ + +/** + * @} + */ +#endif /* TinyAES or CRYP*/ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/hal/stm32f4xx_hal_dac.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c similarity index 100% rename from libs/hal/stm32f4xx_hal_dac.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac.c diff --git a/libs/hal/stm32f4xx_hal_dac_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_dac_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dac_ex.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c new file mode 100644 index 0000000..d117c0e --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi.c @@ -0,0 +1,1161 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dcmi.c + * @author MCD Application Team + * @brief DCMI HAL module driver + * This file provides firmware functions to manage the following + * functionalities of the Digital Camera Interface (DCMI) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Error functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 sequence below describes how to use this driver to capture image + from a camera module connected to the DCMI Interface. + This sequence does not take into account the configuration of the + camera module, which should be made before to configure and enable + the DCMI to capture images. + + (#) Program the required configuration through following parameters: + horizontal and vertical polarity, pixel clock polarity, Capture Rate, + Synchronization Mode, code of the frame delimiter and data width + using HAL_DCMI_Init() function. + + (#) Configure the DMA2_Stream1 channel1 to transfer Data from DCMI DR + register to the destination memory buffer. + + (#) Program the required configuration through following parameters: + DCMI mode, destination memory Buffer address and the data length + and enable capture using HAL_DCMI_Start_DMA() function. + + (#) Optionally, configure and Enable the CROP feature to select a rectangular + window from the received image using HAL_DCMI_ConfigCrop() + and HAL_DCMI_EnableCROP() functions + + (#) The capture can be stopped using HAL_DCMI_Stop() function. + + (#) To control DCMI state you can use the function HAL_DCMI_GetState(). + + *** DCMI HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in DCMI HAL driver. + + (+) __HAL_DCMI_ENABLE: Enable the DCMI peripheral. + (+) __HAL_DCMI_DISABLE: Disable the DCMI peripheral. + (+) __HAL_DCMI_GET_FLAG: Get the DCMI pending flags. + (+) __HAL_DCMI_CLEAR_FLAG: Clear the DCMI pending flags. + (+) __HAL_DCMI_ENABLE_IT: Enable the specified DCMI interrupts. + (+) __HAL_DCMI_DISABLE_IT: Disable the specified DCMI interrupts. + (+) __HAL_DCMI_GET_IT_SOURCE: Check whether the specified DCMI interrupt has occurred or not. + + [..] + (@) You can refer to the DCMI HAL driver header file for more useful macros + + *** Callback registration *** + ============================= + + The compilation define USE_HAL_DCMI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use functions HAL_DCMI_RegisterCallback() to register a user callback. + + Function HAL_DCMI_RegisterCallback() allows to register following callbacks: + (+) FrameEventCallback : DCMI Frame Event. + (+) VsyncEventCallback : DCMI Vsync Event. + (+) LineEventCallback : DCMI Line Event. + (+) ErrorCallback : DCMI error. + (+) MspInitCallback : DCMI MspInit. + (+) MspDeInitCallback : DCMI MspDeInit. + This function takes as parameters the HAL peripheral handle, the callback ID + and a pointer to the user callback function. + + Use function HAL_DCMI_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_DCMI_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the callback ID. + This function allows to reset following callbacks: + (+) FrameEventCallback : DCMI Frame Event. + (+) VsyncEventCallback : DCMI Vsync Event. + (+) LineEventCallback : DCMI Line Event. + (+) ErrorCallback : DCMI error. + (+) MspInitCallback : DCMI MspInit. + (+) MspDeInitCallback : DCMI MspDeInit. + + By default, after the HAL_DCMI_Init and if the state is HAL_DCMI_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions: + examples FrameEventCallback(), HAL_DCMI_ErrorCallback(). + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_DCMI_Init + and HAL_DCMI_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_DCMI_Init and HAL_DCMI_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_DCMI_RegisterCallback before calling HAL_DCMI_DeInit + or HAL_DCMI_Init function. + + When the compilation define USE_HAL_DCMI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +/** @defgroup DCMI DCMI + * @brief DCMI HAL module driver + * @{ + */ + +#ifdef HAL_DCMI_MODULE_ENABLED + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) ||\ + defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) ||\ + defined(STM32F479xx) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define HAL_TIMEOUT_DCMI_STOP 14U /* Set timeout to 1s */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma); +static void DCMI_DMAError(DMA_HandleTypeDef *hdma); + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup DCMI_Exported_Functions DCMI Exported Functions + * @{ + */ + +/** @defgroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the DCMI + (+) De-initialize the DCMI + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the DCMI according to the specified + * parameters in the DCMI_InitTypeDef and create the associated handle. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +__weak HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi) +{ + /* Check the DCMI peripheral state */ + if(hdcmi == NULL) + { + return HAL_ERROR; + } + + /* Check function parameters */ + assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance)); + assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity)); + assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity)); + assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity)); + assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode)); + assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate)); + assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode)); + assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode)); + + if(hdcmi->State == HAL_DCMI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hdcmi->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + /* Init the DCMI Callback settings */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */ + hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */ + hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */ + hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */ + + if(hdcmi->MspInitCallback == NULL) + { + /* Legacy weak MspInit Callback */ + hdcmi->MspInitCallback = HAL_DCMI_MspInit; + } + /* Initialize the low level hardware (MSP) */ + hdcmi->MspInitCallback(hdcmi); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_DCMI_MspInit(hdcmi); +#endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */ + HAL_DCMI_MspInit(hdcmi); + } + + /* Change the DCMI state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Set DCMI parameters */ + /* Configures the HS, VS, DE and PC polarity */ + hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL | DCMI_CR_VSPOL | DCMI_CR_EDM_0 | + DCMI_CR_EDM_1 | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG | + DCMI_CR_ESS); + hdcmi->Instance->CR |= (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate | \ + hdcmi->Init.VSPolarity | hdcmi->Init.HSPolarity | \ + hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode | \ + hdcmi->Init.JPEGMode); + + if(hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED) + { + hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SyncroCode.FrameStartCode) | + ((uint32_t)hdcmi->Init.SyncroCode.LineStartCode << DCMI_POSITION_ESCR_LSC)| + ((uint32_t)hdcmi->Init.SyncroCode.LineEndCode << DCMI_POSITION_ESCR_LEC) | + ((uint32_t)hdcmi->Init.SyncroCode.FrameEndCode << DCMI_POSITION_ESCR_FEC)); + } + + /* Enable the Line, Vsync, Error and Overrun interrupts */ + __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR); + + /* Update error code */ + hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; + + /* Initialize the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Deinitializes the DCMI peripheral registers to their default reset + * values. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_DCMI_DeInit(DCMI_HandleTypeDef *hdcmi) +{ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + if(hdcmi->MspDeInitCallback == NULL) + { + hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit; + } + /* De-Initialize the low level hardware (MSP) */ + hdcmi->MspDeInitCallback(hdcmi); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ + HAL_DCMI_MspDeInit(hdcmi); +#endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */ + + /* Update error code */ + hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; + + /* Initialize the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hdcmi); + + return HAL_OK; +} + +/** + * @brief Initializes the DCMI MSP. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes the DCMI MSP. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_MspDeInit(DCMI_HandleTypeDef* hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ +/** @defgroup DCMI_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure destination address and data length and + Enables DCMI DMA request and enables DCMI capture + (+) Stop the DCMI capture. + (+) Handles DCMI interrupt request. + +@endverbatim + * @{ + */ + +/** + * @brief Enables DCMI DMA request and enables DCMI capture + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @param DCMI_Mode DCMI capture mode snapshot or continuous grab. + * @param pData The destination memory Buffer address (LCD Frame buffer). + * @param Length The length of capture to be transferred. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_Start_DMA(DCMI_HandleTypeDef* hdcmi, uint32_t DCMI_Mode, uint32_t pData, uint32_t Length) +{ + /* Initialize the second memory address */ + uint32_t SecondMemAddress = 0U; + + /* Check function parameters */ + assert_param(IS_DCMI_CAPTURE_MODE(DCMI_Mode)); + + /* Process Locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Enable DCMI by setting DCMIEN bit */ + __HAL_DCMI_ENABLE(hdcmi); + + /* Configure the DCMI Mode */ + hdcmi->Instance->CR &= ~(DCMI_CR_CM); + hdcmi->Instance->CR |= (uint32_t)(DCMI_Mode); + + /* Set the DMA memory0 conversion complete callback */ + hdcmi->DMA_Handle->XferCpltCallback = DCMI_DMAXferCplt; + + /* Set the DMA error callback */ + hdcmi->DMA_Handle->XferErrorCallback = DCMI_DMAError; + + /* Set the dma abort callback */ + hdcmi->DMA_Handle->XferAbortCallback = NULL; + + /* Reset transfer counters value */ + hdcmi->XferCount = 0U; + hdcmi->XferTransferNumber = 0U; + + if(Length <= 0xFFFFU) + { + /* Enable the DMA Stream */ + HAL_DMA_Start_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, Length); + } + else /* DCMI_DOUBLE_BUFFER Mode */ + { + /* Set the DMA memory1 conversion complete callback */ + hdcmi->DMA_Handle->XferM1CpltCallback = DCMI_DMAXferCplt; + + /* Initialize transfer parameters */ + hdcmi->XferCount = 1U; + hdcmi->XferSize = Length; + hdcmi->pBuffPtr = pData; + + /* Get the number of buffer */ + while(hdcmi->XferSize > 0xFFFFU) + { + hdcmi->XferSize = (hdcmi->XferSize/2U); + hdcmi->XferCount = hdcmi->XferCount*2U; + } + + /* Update DCMI counter and transfer number*/ + hdcmi->XferCount = (hdcmi->XferCount - 2U); + hdcmi->XferTransferNumber = hdcmi->XferCount; + + /* Update second memory address */ + SecondMemAddress = (uint32_t)(pData + (4U*hdcmi->XferSize)); + + /* Start DMA multi buffer transfer */ + HAL_DMAEx_MultiBufferStart_IT(hdcmi->DMA_Handle, (uint32_t)&hdcmi->Instance->DR, (uint32_t)pData, SecondMemAddress, hdcmi->XferSize); + } + + /* Enable Capture */ + hdcmi->Instance->CR |= DCMI_CR_CAPTURE; + + /* Release Lock */ + __HAL_UNLOCK(hdcmi); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Disable DCMI DMA request and Disable DCMI capture + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_Stop(DCMI_HandleTypeDef* hdcmi) +{ + __IO uint32_t count = SystemCoreClock / HAL_TIMEOUT_DCMI_STOP; + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Disable Capture */ + hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE); + + /* Check if the DCMI capture effectively disabled */ + do + { + if (count-- == 0U) + { + /* Update error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT; + + status = HAL_TIMEOUT; + break; + } + } + while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0U); + + /* Disable the DCMI */ + __HAL_DCMI_DISABLE(hdcmi); + + /* Disable the DMA */ + HAL_DMA_Abort(hdcmi->DMA_Handle); + + /* Update error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_NONE; + + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + /* Return function status */ + return status; +} + +/** + * @brief Suspend DCMI capture + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_Suspend(DCMI_HandleTypeDef* hdcmi) +{ + __IO uint32_t count = SystemCoreClock / HAL_TIMEOUT_DCMI_STOP; + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdcmi); + + if(hdcmi->State == HAL_DCMI_STATE_BUSY) + { + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_SUSPENDED; + + /* Disable Capture */ + hdcmi->Instance->CR &= ~(DCMI_CR_CAPTURE); + + /* Check if the DCMI capture effectively disabled */ + do + { + if (count-- == 0U) + { + /* Update error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_TIMEOUT; + + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_READY; + + status = HAL_TIMEOUT; + break; + } + } + while((hdcmi->Instance->CR & DCMI_CR_CAPTURE) != 0); + } + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + /* Return function status */ + return status; +} + +/** + * @brief Resume DCMI capture + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_Resume(DCMI_HandleTypeDef* hdcmi) +{ + /* Process locked */ + __HAL_LOCK(hdcmi); + + if(hdcmi->State == HAL_DCMI_STATE_SUSPENDED) + { + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Disable Capture */ + hdcmi->Instance->CR |= DCMI_CR_CAPTURE; + } + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Handles DCMI interrupt request. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for the DCMI. + * @retval None + */ +void HAL_DCMI_IRQHandler(DCMI_HandleTypeDef *hdcmi) +{ + uint32_t isr_value = READ_REG(hdcmi->Instance->MISR); + + /* Synchronization error interrupt management *******************************/ + if((isr_value & DCMI_FLAG_ERRRI) == DCMI_FLAG_ERRRI) + { + /* Clear the Synchronization error flag */ + __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_ERRRI); + + /* Update error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_SYNC; + + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_ERROR; + + /* Set the synchronization error callback */ + hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError; + + /* Abort the DMA Transfer */ + HAL_DMA_Abort_IT(hdcmi->DMA_Handle); + } + /* Overflow interrupt management ********************************************/ + if((isr_value & DCMI_FLAG_OVRRI) == DCMI_FLAG_OVRRI) + { + /* Clear the Overflow flag */ + __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_OVRRI); + + /* Update error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_OVR; + + /* Change DCMI state */ + hdcmi->State = HAL_DCMI_STATE_ERROR; + + /* Set the overflow callback */ + hdcmi->DMA_Handle->XferAbortCallback = DCMI_DMAError; + + /* Abort the DMA Transfer */ + HAL_DMA_Abort_IT(hdcmi->DMA_Handle); + } + /* Line Interrupt management ************************************************/ + if((isr_value & DCMI_FLAG_LINERI) == DCMI_FLAG_LINERI) + { + /* Clear the Line interrupt flag */ + __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_LINERI); + + /* Line interrupt Callback */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + /*Call registered DCMI line event callback*/ + hdcmi->LineEventCallback(hdcmi); +#else + HAL_DCMI_LineEventCallback(hdcmi); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + } + /* VSYNC interrupt management ***********************************************/ + if((isr_value & DCMI_FLAG_VSYNCRI) == DCMI_FLAG_VSYNCRI) + { + /* Clear the VSYNC flag */ + __HAL_DCMI_CLEAR_FLAG(hdcmi, DCMI_FLAG_VSYNCRI); + + /* VSYNC Callback */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + /*Call registered DCMI vsync event callback*/ + hdcmi->VsyncEventCallback(hdcmi); +#else + HAL_DCMI_VsyncEventCallback(hdcmi); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + } + /* FRAME interrupt management ***********************************************/ + if((isr_value & DCMI_FLAG_FRAMERI) == DCMI_FLAG_FRAMERI) + { + /* When snapshot mode, disable Vsync, Error and Overrun interrupts */ + if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT) + { + /* Disable the Line, Vsync, Error and Overrun interrupts */ + __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR); + } + + /* Disable the Frame interrupt */ + __HAL_DCMI_DISABLE_IT(hdcmi, DCMI_IT_FRAME); + + /* Frame Callback */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + /*Call registered DCMI frame event callback*/ + hdcmi->FrameEventCallback(hdcmi); +#else + HAL_DCMI_FrameEventCallback(hdcmi); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Error DCMI callback. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Line Event callback. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_LineEventCallback could be implemented in the user file + */ +} + +/** + * @brief VSYNC Event callback. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_VsyncEventCallback could be implemented in the user file + */ +} + +/** + * @brief Frame Event callback. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval None + */ +__weak void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdcmi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DCMI_FrameEventCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup DCMI_Exported_Functions_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== +[..] This section provides functions allowing to: + (+) Configure the CROP feature. + (+) Enable/Disable the CROP feature. + +@endverbatim + * @{ + */ + +/** + * @brief Configure the DCMI CROP coordinate. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @param X0 DCMI window X offset + * @param Y0 DCMI window Y offset + * @param XSize DCMI Pixel per line + * @param YSize DCMI Line number + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_ConfigCrop(DCMI_HandleTypeDef *hdcmi, uint32_t X0, uint32_t Y0, uint32_t XSize, uint32_t YSize) +{ + /* Process Locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Check the parameters */ + assert_param(IS_DCMI_WINDOW_COORDINATE(X0)); + assert_param(IS_DCMI_WINDOW_COORDINATE(YSize)); + assert_param(IS_DCMI_WINDOW_COORDINATE(XSize)); + assert_param(IS_DCMI_WINDOW_HEIGHT(Y0)); + + /* Configure CROP */ + hdcmi->Instance->CWSIZER = (XSize | (YSize << DCMI_POSITION_CWSIZE_VLINE)); + hdcmi->Instance->CWSTRTR = (X0 | (Y0 << DCMI_POSITION_CWSTRT_VST)); + + /* Initialize the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + return HAL_OK; +} + +/** + * @brief Disable the Crop feature. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_DisableCrop(DCMI_HandleTypeDef *hdcmi) +{ + /* Process Locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Disable DCMI Crop feature */ + hdcmi->Instance->CR &= ~(uint32_t)DCMI_CR_CROP; + + /* Change the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + return HAL_OK; +} + +/** + * @brief Enable the Crop feature. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_EnableCrop(DCMI_HandleTypeDef *hdcmi) +{ + /* Process Locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Enable DCMI Crop feature */ + hdcmi->Instance->CR |= (uint32_t)DCMI_CR_CROP; + + /* Change the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + return HAL_OK; +} + +/** + * @brief Set embedded synchronization delimiters unmasks. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @param SyncUnmask pointer to a DCMI_SyncUnmaskTypeDef structure that contains + * the embedded synchronization delimiters unmasks. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_ConfigSyncUnmask(DCMI_HandleTypeDef *hdcmi, DCMI_SyncUnmaskTypeDef *SyncUnmask) +{ + /* Process Locked */ + __HAL_LOCK(hdcmi); + + /* Lock the DCMI peripheral state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + + /* Write DCMI embedded synchronization unmask register */ + hdcmi->Instance->ESUR = (((uint32_t)SyncUnmask->FrameStartUnmask) |\ + ((uint32_t)SyncUnmask->LineStartUnmask << DCMI_ESUR_LSU_Pos)|\ + ((uint32_t)SyncUnmask->LineEndUnmask << DCMI_ESUR_LEU_Pos)|\ + ((uint32_t)SyncUnmask->FrameEndUnmask << DCMI_ESUR_FEU_Pos)); + + /* Change the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdcmi); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup DCMI_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the DCMI state. + (+) Get the specific DCMI error flag. + +@endverbatim + * @{ + */ + +/** + * @brief Return the DCMI state + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL state + */ +HAL_DCMI_StateTypeDef HAL_DCMI_GetState(DCMI_HandleTypeDef *hdcmi) +{ + return hdcmi->State; +} + +/** + * @brief Return the DCMI error code + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval DCMI Error Code + */ +uint32_t HAL_DCMI_GetError(DCMI_HandleTypeDef *hdcmi) +{ + return hdcmi->ErrorCode; +} + +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) +/** + * @brief DCMI Callback registering + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @param CallbackID dcmi Callback ID + * @param pCallback pointer to DCMI_CallbackTypeDef structure + * @retval status + */ +HAL_StatusTypeDef HAL_DCMI_RegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID, pDCMI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + else + { + if(hdcmi->State == HAL_DCMI_STATE_READY) + { + switch (CallbackID) + { + case HAL_DCMI_FRAME_EVENT_CB_ID : + hdcmi->FrameEventCallback = pCallback; + break; + + case HAL_DCMI_VSYNC_EVENT_CB_ID : + hdcmi->VsyncEventCallback = pCallback; + break; + + case HAL_DCMI_LINE_EVENT_CB_ID : + hdcmi->LineEventCallback = pCallback; + break; + + case HAL_DCMI_ERROR_CB_ID : + hdcmi->ErrorCallback = pCallback; + break; + + case HAL_DCMI_MSPINIT_CB_ID : + hdcmi->MspInitCallback = pCallback; + break; + + case HAL_DCMI_MSPDEINIT_CB_ID : + hdcmi->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if(hdcmi->State == HAL_DCMI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_DCMI_MSPINIT_CB_ID : + hdcmi->MspInitCallback = pCallback; + break; + + case HAL_DCMI_MSPDEINIT_CB_ID : + hdcmi->MspDeInitCallback = pCallback; + break; + + default : + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + } + + return status; +} + +/** + * @brief DCMI Callback Unregistering + * @param hdcmi dcmi handle + * @param CallbackID dcmi Callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_DCMI_UnRegisterCallback(DCMI_HandleTypeDef *hdcmi, HAL_DCMI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(hdcmi->State == HAL_DCMI_STATE_READY) + { + switch (CallbackID) + { + case HAL_DCMI_FRAME_EVENT_CB_ID : + hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */ + break; + + case HAL_DCMI_VSYNC_EVENT_CB_ID : + hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */ + break; + + case HAL_DCMI_LINE_EVENT_CB_ID : + hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */ + break; + + case HAL_DCMI_ERROR_CB_ID : + hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_DCMI_MSPINIT_CB_ID : + hdcmi->MspInitCallback = HAL_DCMI_MspInit; + break; + + case HAL_DCMI_MSPDEINIT_CB_ID : + hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit; + break; + + default : + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(hdcmi->State == HAL_DCMI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_DCMI_MSPINIT_CB_ID : + hdcmi->MspInitCallback = HAL_DCMI_MspInit; + break; + + case HAL_DCMI_MSPDEINIT_CB_ID : + hdcmi->MspDeInitCallback = HAL_DCMI_MspDeInit; + break; + + default : + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hdcmi->ErrorCode |= HAL_DCMI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + +/** + * @} + */ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup DCMI_Private_Functions DCMI Private Functions + * @{ + */ + +/** + * @brief DMA conversion complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void DCMI_DMAXferCplt(DMA_HandleTypeDef *hdma) +{ + uint32_t tmp = 0U; + + DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + if(hdcmi->XferCount != 0U) + { + /* Update memory 0 address location */ + tmp = ((hdcmi->DMA_Handle->Instance->CR) & DMA_SxCR_CT); + if(((hdcmi->XferCount % 2U) == 0U) && (tmp != 0U)) + { + tmp = hdcmi->DMA_Handle->Instance->M0AR; + HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8U*hdcmi->XferSize)), MEMORY0); + hdcmi->XferCount--; + } + /* Update memory 1 address location */ + else if((hdcmi->DMA_Handle->Instance->CR & DMA_SxCR_CT) == 0U) + { + tmp = hdcmi->DMA_Handle->Instance->M1AR; + HAL_DMAEx_ChangeMemory(hdcmi->DMA_Handle, (tmp + (8U*hdcmi->XferSize)), MEMORY1); + hdcmi->XferCount--; + } + } + /* Update memory 0 address location */ + else if((hdcmi->DMA_Handle->Instance->CR & DMA_SxCR_CT) != 0U) + { + hdcmi->DMA_Handle->Instance->M0AR = hdcmi->pBuffPtr; + } + /* Update memory 1 address location */ + else if((hdcmi->DMA_Handle->Instance->CR & DMA_SxCR_CT) == 0U) + { + tmp = hdcmi->pBuffPtr; + hdcmi->DMA_Handle->Instance->M1AR = (tmp + (4U*hdcmi->XferSize)); + hdcmi->XferCount = hdcmi->XferTransferNumber; + } + + /* Check if the frame is transferred */ + if(hdcmi->XferCount == hdcmi->XferTransferNumber) + { + /* Enable the Frame interrupt */ + __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_FRAME); + + /* When snapshot mode, set dcmi state to ready */ + if((hdcmi->Instance->CR & DCMI_CR_CM) == DCMI_MODE_SNAPSHOT) + { + hdcmi->State= HAL_DCMI_STATE_READY; + } + } +} + +/** + * @brief DMA error callback + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void DCMI_DMAError(DMA_HandleTypeDef *hdma) +{ + DCMI_HandleTypeDef* hdcmi = ( DCMI_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + if(hdcmi->DMA_Handle->ErrorCode != HAL_DMA_ERROR_FE) + { + /* Initialize the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + } + + /* DCMI error Callback */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + /*Call registered DCMI error callback*/ + hdcmi->ErrorCallback(hdcmi); +#else + HAL_DCMI_ErrorCallback(hdcmi); +#endif /* USE_HAL_DCMI_REGISTER_CALLBACKS */ + +} + +/** + * @} + */ + +/** + * @} + */ +#endif /* STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\ + STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\ + STM32F479xx */ +#endif /* HAL_DCMI_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c new file mode 100644 index 0000000..bbc64c6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dcmi_ex.c @@ -0,0 +1,182 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dcmi_ex.c + * @author MCD Application Team + * @brief DCMI Extension HAL module driver + * This file provides firmware functions to manage the following + * functionalities of DCMI extension peripheral: + * + Extension features functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 + ============================================================================== + ##### DCMI peripheral extension features ##### + ============================================================================== + + [..] Comparing to other previous devices, the DCMI interface for STM32F446xx + devices contains the following additional features : + + (+) Support of Black and White cameras + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to manage the Black and White feature + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +/** @defgroup DCMIEx DCMIEx + * @brief DCMI Extended HAL module driver + * @{ + */ + +#ifdef HAL_DCMI_MODULE_ENABLED + +#if defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) ||\ + defined(STM32F439xx) || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup DCMIEx_Exported_Functions DCMI Extended Exported Functions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup DCMI_Exported_Functions_Group1 Initialization and Configuration functions + * @{ + */ + +/** + * @brief Initializes the DCMI according to the specified + * parameters in the DCMI_InitTypeDef and create the associated handle. + * @param hdcmi pointer to a DCMI_HandleTypeDef structure that contains + * the configuration information for DCMI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DCMI_Init(DCMI_HandleTypeDef *hdcmi) +{ + /* Check the DCMI peripheral state */ + if(hdcmi == NULL) + { + return HAL_ERROR; + } + + /* Check function parameters */ + assert_param(IS_DCMI_ALL_INSTANCE(hdcmi->Instance)); + assert_param(IS_DCMI_PCKPOLARITY(hdcmi->Init.PCKPolarity)); + assert_param(IS_DCMI_VSPOLARITY(hdcmi->Init.VSPolarity)); + assert_param(IS_DCMI_HSPOLARITY(hdcmi->Init.HSPolarity)); + assert_param(IS_DCMI_SYNCHRO(hdcmi->Init.SynchroMode)); + assert_param(IS_DCMI_CAPTURE_RATE(hdcmi->Init.CaptureRate)); + assert_param(IS_DCMI_EXTENDED_DATA(hdcmi->Init.ExtendedDataMode)); + assert_param(IS_DCMI_MODE_JPEG(hdcmi->Init.JPEGMode)); +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) + assert_param(IS_DCMI_BYTE_SELECT_MODE(hdcmi->Init.ByteSelectMode)); + assert_param(IS_DCMI_BYTE_SELECT_START(hdcmi->Init.ByteSelectStart)); + assert_param(IS_DCMI_LINE_SELECT_MODE(hdcmi->Init.LineSelectMode)); + assert_param(IS_DCMI_LINE_SELECT_START(hdcmi->Init.LineSelectStart)); +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ + if(hdcmi->State == HAL_DCMI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hdcmi->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + /* Init the DCMI Callback settings */ +#if (USE_HAL_DCMI_REGISTER_CALLBACKS == 1) + hdcmi->FrameEventCallback = HAL_DCMI_FrameEventCallback; /* Legacy weak FrameEventCallback */ + hdcmi->VsyncEventCallback = HAL_DCMI_VsyncEventCallback; /* Legacy weak VsyncEventCallback */ + hdcmi->LineEventCallback = HAL_DCMI_LineEventCallback; /* Legacy weak LineEventCallback */ + hdcmi->ErrorCallback = HAL_DCMI_ErrorCallback; /* Legacy weak ErrorCallback */ + + if(hdcmi->MspInitCallback == NULL) + { + /* Legacy weak MspInit Callback */ + hdcmi->MspInitCallback = HAL_DCMI_MspInit; + } + /* Initialize the low level hardware (MSP) */ + hdcmi->MspInitCallback(hdcmi); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_DCMI_MspInit(hdcmi); +#endif /* (USE_HAL_DCMI_REGISTER_CALLBACKS) */ + HAL_DCMI_MspInit(hdcmi); + } + + /* Change the DCMI state */ + hdcmi->State = HAL_DCMI_STATE_BUSY; + /* Configures the HS, VS, DE and PC polarity */ + hdcmi->Instance->CR &= ~(DCMI_CR_PCKPOL | DCMI_CR_HSPOL | DCMI_CR_VSPOL | DCMI_CR_EDM_0 |\ + DCMI_CR_EDM_1 | DCMI_CR_FCRC_0 | DCMI_CR_FCRC_1 | DCMI_CR_JPEG |\ + DCMI_CR_ESS +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) + | DCMI_CR_BSM_0 | DCMI_CR_BSM_1 | DCMI_CR_OEBS |\ + DCMI_CR_LSM | DCMI_CR_OELS +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ + ); + hdcmi->Instance->CR |= (uint32_t)(hdcmi->Init.SynchroMode | hdcmi->Init.CaptureRate |\ + hdcmi->Init.VSPolarity | hdcmi->Init.HSPolarity |\ + hdcmi->Init.PCKPolarity | hdcmi->Init.ExtendedDataMode |\ + hdcmi->Init.JPEGMode +#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) + | hdcmi->Init.ByteSelectMode |\ + hdcmi->Init.ByteSelectStart | hdcmi->Init.LineSelectMode |\ + hdcmi->Init.LineSelectStart +#endif /* STM32F446xx || STM32F469xx || STM32F479xx */ + ); + if(hdcmi->Init.SynchroMode == DCMI_SYNCHRO_EMBEDDED) + { + hdcmi->Instance->ESCR = (((uint32_t)hdcmi->Init.SyncroCode.FrameStartCode) | + ((uint32_t)hdcmi->Init.SyncroCode.LineStartCode << DCMI_POSITION_ESCR_LSC)| + ((uint32_t)hdcmi->Init.SyncroCode.LineEndCode << DCMI_POSITION_ESCR_LEC) | + ((uint32_t)hdcmi->Init.SyncroCode.FrameEndCode << DCMI_POSITION_ESCR_FEC)); + + } + + /* Enable the Line, Vsync, Error and Overrun interrupts */ + __HAL_DCMI_ENABLE_IT(hdcmi, DCMI_IT_LINE | DCMI_IT_VSYNC | DCMI_IT_ERR | DCMI_IT_OVR); + + /* Update error code */ + hdcmi->ErrorCode = HAL_DCMI_ERROR_NONE; + + /* Initialize the DCMI state*/ + hdcmi->State = HAL_DCMI_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ +#endif /* STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx ||\ + STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */ +#endif /* HAL_DCMI_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c new file mode 100644 index 0000000..63126be --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dfsdm.c @@ -0,0 +1,4423 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dfsdm.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the Digital Filter for Sigma-Delta Modulators + * (DFSDM) peripherals: + * + Initialization and configuration of channels and filters + * + Regular channels configuration + * + Injected channels configuration + * + Regular/Injected Channels DMA Configuration + * + Interrupts and flags management + * + Analog watchdog feature + * + Short-circuit detector feature + * + Extremes detector feature + * + Clock absence detector feature + * + Break generation on analog watchdog or short-circuit event + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + *** Channel initialization *** + ============================== + [..] + (#) User has first to initialize channels (before filters initialization). + (#) As prerequisite, fill in the HAL_DFSDM_ChannelMspInit() : + (++) Enable DFSDMz clock interface with __HAL_RCC_DFSDMz_CLK_ENABLE(). + (++) Enable the clocks for the DFSDMz GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE(). + (++) Configure these DFSDMz pins in alternate mode using HAL_GPIO_Init(). + (++) If interrupt mode is used, enable and configure DFSDMz_FLT0 global + interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + (#) Configure the output clock, input, serial interface, analog watchdog, + offset and data right bit shift parameters for this channel using the + HAL_DFSDM_ChannelInit() function. + + *** Channel clock absence detector *** + ====================================== + [..] + (#) Start clock absence detector using HAL_DFSDM_ChannelCkabStart() or + HAL_DFSDM_ChannelCkabStart_IT(). + (#) In polling mode, use HAL_DFSDM_ChannelPollForCkab() to detect the clock + absence. + (#) In interrupt mode, HAL_DFSDM_ChannelCkabCallback() will be called if + clock absence is detected. + (#) Stop clock absence detector using HAL_DFSDM_ChannelCkabStop() or + HAL_DFSDM_ChannelCkabStop_IT(). + (#) Please note that the same mode (polling or interrupt) has to be used + for all channels because the channels are sharing the same interrupt. + (#) Please note also that in interrupt mode, if clock absence detector is + stopped for one channel, interrupt will be disabled for all channels. + + *** Channel short circuit detector *** + ====================================== + [..] + (#) Start short circuit detector using HAL_DFSDM_ChannelScdStart() or + or HAL_DFSDM_ChannelScdStart_IT(). + (#) In polling mode, use HAL_DFSDM_ChannelPollForScd() to detect short + circuit. + (#) In interrupt mode, HAL_DFSDM_ChannelScdCallback() will be called if + short circuit is detected. + (#) Stop short circuit detector using HAL_DFSDM_ChannelScdStop() or + or HAL_DFSDM_ChannelScdStop_IT(). + (#) Please note that the same mode (polling or interrupt) has to be used + for all channels because the channels are sharing the same interrupt. + (#) Please note also that in interrupt mode, if short circuit detector is + stopped for one channel, interrupt will be disabled for all channels. + + *** Channel analog watchdog value *** + ===================================== + [..] + (#) Get analog watchdog filter value of a channel using + HAL_DFSDM_ChannelGetAwdValue(). + + *** Channel offset value *** + ===================================== + [..] + (#) Modify offset value of a channel using HAL_DFSDM_ChannelModifyOffset(). + + *** Filter initialization *** + ============================= + [..] + (#) After channel initialization, user has to init filters. + (#) As prerequisite, fill in the HAL_DFSDM_FilterMspInit() : + (++) If interrupt mode is used , enable and configure DFSDMz_FLTx global + interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + Please note that DFSDMz_FLT0 global interrupt could be already + enabled if interrupt is used for channel. + (++) If DMA mode is used, configure DMA with HAL_DMA_Init() and link it + with DFSDMz filter handle using __HAL_LINKDMA(). + (#) Configure the regular conversion, injected conversion and filter + parameters for this filter using the HAL_DFSDM_FilterInit() function. + + *** Filter regular channel conversion *** + ========================================= + [..] + (#) Select regular channel and enable/disable continuous mode using + HAL_DFSDM_FilterConfigRegChannel(). + (#) Start regular conversion using HAL_DFSDM_FilterRegularStart(), + HAL_DFSDM_FilterRegularStart_IT(), HAL_DFSDM_FilterRegularStart_DMA() or + HAL_DFSDM_FilterRegularMsbStart_DMA(). + (#) In polling mode, use HAL_DFSDM_FilterPollForRegConversion() to detect + the end of regular conversion. + (#) In interrupt mode, HAL_DFSDM_FilterRegConvCpltCallback() will be called + at the end of regular conversion. + (#) Get value of regular conversion and corresponding channel using + HAL_DFSDM_FilterGetRegularValue(). + (#) In DMA mode, HAL_DFSDM_FilterRegConvHalfCpltCallback() and + HAL_DFSDM_FilterRegConvCpltCallback() will be called respectively at the + half transfer and at the transfer complete. Please note that + HAL_DFSDM_FilterRegConvHalfCpltCallback() will be called only in DMA + circular mode. + (#) Stop regular conversion using HAL_DFSDM_FilterRegularStop(), + HAL_DFSDM_FilterRegularStop_IT() or HAL_DFSDM_FilterRegularStop_DMA(). + + *** Filter injected channels conversion *** + =========================================== + [..] + (#) Select injected channels using HAL_DFSDM_FilterConfigInjChannel(). + (#) Start injected conversion using HAL_DFSDM_FilterInjectedStart(), + HAL_DFSDM_FilterInjectedStart_IT(), HAL_DFSDM_FilterInjectedStart_DMA() or + HAL_DFSDM_FilterInjectedMsbStart_DMA(). + (#) In polling mode, use HAL_DFSDM_FilterPollForInjConversion() to detect + the end of injected conversion. + (#) In interrupt mode, HAL_DFSDM_FilterInjConvCpltCallback() will be called + at the end of injected conversion. + (#) Get value of injected conversion and corresponding channel using + HAL_DFSDM_FilterGetInjectedValue(). + (#) In DMA mode, HAL_DFSDM_FilterInjConvHalfCpltCallback() and + HAL_DFSDM_FilterInjConvCpltCallback() will be called respectively at the + half transfer and at the transfer complete. Please note that + HAL_DFSDM_FilterInjConvCpltCallback() will be called only in DMA + circular mode. + (#) Stop injected conversion using HAL_DFSDM_FilterInjectedStop(), + HAL_DFSDM_FilterInjectedStop_IT() or HAL_DFSDM_FilterInjectedStop_DMA(). + + *** Filter analog watchdog *** + ============================== + [..] + (#) Start filter analog watchdog using HAL_DFSDM_FilterAwdStart_IT(). + (#) HAL_DFSDM_FilterAwdCallback() will be called if analog watchdog occurs. + (#) Stop filter analog watchdog using HAL_DFSDM_FilterAwdStop_IT(). + + *** Filter extreme detector *** + =============================== + [..] + (#) Start filter extreme detector using HAL_DFSDM_FilterExdStart(). + (#) Get extreme detector maximum value using HAL_DFSDM_FilterGetExdMaxValue(). + (#) Get extreme detector minimum value using HAL_DFSDM_FilterGetExdMinValue(). + (#) Start filter extreme detector using HAL_DFSDM_FilterExdStop(). + + *** Filter conversion time *** + ============================== + [..] + (#) Get conversion time value using HAL_DFSDM_FilterGetConvTimeValue(). + + *** Callback registration *** + ============================= + [..] + The compilation define USE_HAL_DFSDM_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use functions HAL_DFSDM_Channel_RegisterCallback(), + HAL_DFSDM_Filter_RegisterCallback() or + HAL_DFSDM_Filter_RegisterAwdCallback() to register a user callback. + + [..] + Function HAL_DFSDM_Channel_RegisterCallback() allows to register + following callbacks: + (+) CkabCallback : DFSDM channel clock absence detection callback. + (+) ScdCallback : DFSDM channel short circuit detection callback. + (+) MspInitCallback : DFSDM channel MSP init callback. + (+) MspDeInitCallback : DFSDM channel MSP de-init callback. + [..] + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Function HAL_DFSDM_Filter_RegisterCallback() allows to register + following callbacks: + (+) RegConvCpltCallback : DFSDM filter regular conversion complete callback. + (+) RegConvHalfCpltCallback : DFSDM filter half regular conversion complete callback. + (+) InjConvCpltCallback : DFSDM filter injected conversion complete callback. + (+) InjConvHalfCpltCallback : DFSDM filter half injected conversion complete callback. + (+) ErrorCallback : DFSDM filter error callback. + (+) MspInitCallback : DFSDM filter MSP init callback. + (+) MspDeInitCallback : DFSDM filter MSP de-init callback. + [..] + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + For specific DFSDM filter analog watchdog callback use dedicated register callback: + HAL_DFSDM_Filter_RegisterAwdCallback(). + + [..] + Use functions HAL_DFSDM_Channel_UnRegisterCallback() or + HAL_DFSDM_Filter_UnRegisterCallback() to reset a callback to the default + weak function. + + [..] + HAL_DFSDM_Channel_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + [..] + This function allows to reset following callbacks: + (+) CkabCallback : DFSDM channel clock absence detection callback. + (+) ScdCallback : DFSDM channel short circuit detection callback. + (+) MspInitCallback : DFSDM channel MSP init callback. + (+) MspDeInitCallback : DFSDM channel MSP de-init callback. + + [..] + HAL_DFSDM_Filter_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + [..] + This function allows to reset following callbacks: + (+) RegConvCpltCallback : DFSDM filter regular conversion complete callback. + (+) RegConvHalfCpltCallback : DFSDM filter half regular conversion complete callback. + (+) InjConvCpltCallback : DFSDM filter injected conversion complete callback. + (+) InjConvHalfCpltCallback : DFSDM filter half injected conversion complete callback. + (+) ErrorCallback : DFSDM filter error callback. + (+) MspInitCallback : DFSDM filter MSP init callback. + (+) MspDeInitCallback : DFSDM filter MSP de-init callback. + + [..] + For specific DFSDM filter analog watchdog callback use dedicated unregister callback: + HAL_DFSDM_Filter_UnRegisterAwdCallback(). + + [..] + By default, after the call of init function and if the state is RESET + all callbacks are reset to the corresponding legacy weak functions: + examples HAL_DFSDM_ChannelScdCallback(), HAL_DFSDM_FilterErrorCallback(). + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak functions in the init and de-init only when these + callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the init and de-init keep and use + the user MspInit/MspDeInit callbacks (registered beforehand) + + [..] + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used + during the init/de-init. + In that case first register the MspInit/MspDeInit user callbacks using + HAL_DFSDM_Channel_RegisterCallback() or + HAL_DFSDM_Filter_RegisterCallback() before calling init or de-init function. + + [..] + When The compilation define USE_HAL_DFSDM_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#ifdef HAL_DFSDM_MODULE_ENABLED +#if defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) +/** @defgroup DFSDM DFSDM + * @brief DFSDM HAL driver module + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup DFSDM_Private_Define DFSDM Private Define + * @{ + */ + +#define DFSDM_FLTCR1_MSB_RCH_OFFSET 8U + +#define DFSDM_MSB_MASK 0xFFFF0000U +#define DFSDM_LSB_MASK 0x0000FFFFU +#define DFSDM_CKAB_TIMEOUT 5000U +#define DFSDM1_CHANNEL_NUMBER 4U +#if defined (DFSDM2_Channel0) +#define DFSDM2_CHANNEL_NUMBER 8U +#endif /* DFSDM2_Channel0 */ + +/** + * @} + */ +/** @addtogroup DFSDM_Private_Macros +* @{ +*/ + +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup DFSDM_Private_Variables DFSDM Private Variables + * @{ + */ +__IO uint32_t v_dfsdm1ChannelCounter = 0U; +DFSDM_Channel_HandleTypeDef* a_dfsdm1ChannelHandle[DFSDM1_CHANNEL_NUMBER] = {NULL}; + +#if defined (DFSDM2_Channel0) +__IO uint32_t v_dfsdm2ChannelCounter = 0U; +DFSDM_Channel_HandleTypeDef* a_dfsdm2ChannelHandle[DFSDM2_CHANNEL_NUMBER] = {NULL}; +#endif /* DFSDM2_Channel0 */ +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup DFSDM_Private_Functions DFSDM Private Functions + * @{ + */ +static uint32_t DFSDM_GetInjChannelsNbr(uint32_t Channels); +static uint32_t DFSDM_GetChannelFromInstance(const DFSDM_Channel_TypeDef *Instance); +static void DFSDM_RegConvStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); +static void DFSDM_RegConvStop(DFSDM_Filter_HandleTypeDef* hdfsdm_filter); +static void DFSDM_InjConvStart(DFSDM_Filter_HandleTypeDef* hdfsdm_filter); +static void DFSDM_InjConvStop(DFSDM_Filter_HandleTypeDef* hdfsdm_filter); +static void DFSDM_DMARegularHalfConvCplt(DMA_HandleTypeDef *hdma); +static void DFSDM_DMARegularConvCplt(DMA_HandleTypeDef *hdma); +static void DFSDM_DMAInjectedHalfConvCplt(DMA_HandleTypeDef *hdma); +static void DFSDM_DMAInjectedConvCplt(DMA_HandleTypeDef *hdma); +static void DFSDM_DMAError(DMA_HandleTypeDef *hdma); + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DFSDM_Exported_Functions DFSDM Exported Functions + * @{ + */ + +/** @defgroup DFSDM_Exported_Functions_Group1_Channel Channel initialization and de-initialization functions + * @brief Channel initialization and de-initialization functions + * +@verbatim + ============================================================================== + ##### Channel initialization and de-initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the DFSDM channel. + (+) De-initialize the DFSDM channel. +@endverbatim + * @{ + */ + +/** + * @brief Initialize the DFSDM channel according to the specified parameters + * in the DFSDM_ChannelInitTypeDef structure and initialize the associated handle. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ +#if defined(DFSDM2_Channel0) + __IO uint32_t* channelCounterPtr; + DFSDM_Channel_HandleTypeDef **channelHandleTable; + DFSDM_Channel_TypeDef* channel0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check DFSDM Channel handle */ + if(hdfsdm_channel == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + assert_param(IS_FUNCTIONAL_STATE(hdfsdm_channel->Init.OutputClock.Activation)); + assert_param(IS_DFSDM_CHANNEL_INPUT(hdfsdm_channel->Init.Input.Multiplexer)); + assert_param(IS_DFSDM_CHANNEL_DATA_PACKING(hdfsdm_channel->Init.Input.DataPacking)); + assert_param(IS_DFSDM_CHANNEL_INPUT_PINS(hdfsdm_channel->Init.Input.Pins)); + assert_param(IS_DFSDM_CHANNEL_SERIAL_INTERFACE_TYPE(hdfsdm_channel->Init.SerialInterface.Type)); + assert_param(IS_DFSDM_CHANNEL_SPI_CLOCK(hdfsdm_channel->Init.SerialInterface.SpiClock)); + assert_param(IS_DFSDM_CHANNEL_FILTER_ORDER(hdfsdm_channel->Init.Awd.FilterOrder)); + assert_param(IS_DFSDM_CHANNEL_FILTER_OVS_RATIO(hdfsdm_channel->Init.Awd.Oversampling)); + assert_param(IS_DFSDM_CHANNEL_OFFSET(hdfsdm_channel->Init.Offset)); + assert_param(IS_DFSDM_CHANNEL_RIGHT_BIT_SHIFT(hdfsdm_channel->Init.RightBitShift)); + +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + channelCounterPtr = &v_dfsdm1ChannelCounter; + channelHandleTable = a_dfsdm1ChannelHandle; + channel0Instance = DFSDM1_Channel0; + } + else + { + channelCounterPtr = &v_dfsdm2ChannelCounter; + channelHandleTable = a_dfsdm2ChannelHandle; + channel0Instance = DFSDM2_Channel0; + } + + /* Check that channel has not been already initialized */ + if(channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] != NULL) + { + return HAL_ERROR; + } + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + /* Reset callback pointers to the weak predefined callbacks */ + hdfsdm_channel->CkabCallback = HAL_DFSDM_ChannelCkabCallback; + hdfsdm_channel->ScdCallback = HAL_DFSDM_ChannelScdCallback; + + /* Call MSP init function */ + if(hdfsdm_channel->MspInitCallback == NULL) + { + hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit; + } + hdfsdm_channel->MspInitCallback(hdfsdm_channel); +#else + /* Call MSP init function */ + HAL_DFSDM_ChannelMspInit(hdfsdm_channel); +#endif + + /* Update the channel counter */ + (*channelCounterPtr)++; + + /* Configure output serial clock and enable global DFSDM interface only for first channel */ + if(*channelCounterPtr == 1U) + { + assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK(hdfsdm_channel->Init.OutputClock.Selection)); + /* Set the output serial clock source */ + channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTSRC); + channel0Instance->CHCFGR1 |= hdfsdm_channel->Init.OutputClock.Selection; + + /* Reset clock divider */ + channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTDIV); + if(hdfsdm_channel->Init.OutputClock.Activation == ENABLE) + { + assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK_DIVIDER(hdfsdm_channel->Init.OutputClock.Divider)); + /* Set the output clock divider */ + channel0Instance->CHCFGR1 |= (uint32_t) ((hdfsdm_channel->Init.OutputClock.Divider - 1U) << + DFSDM_CHCFGR1_CKOUTDIV_Pos); + } + + /* enable the DFSDM global interface */ + channel0Instance->CHCFGR1 |= DFSDM_CHCFGR1_DFSDMEN; + } + + /* Set channel input parameters */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_DATPACK | DFSDM_CHCFGR1_DATMPX | + DFSDM_CHCFGR1_CHINSEL); + hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.Input.Multiplexer | + hdfsdm_channel->Init.Input.DataPacking | + hdfsdm_channel->Init.Input.Pins); + + /* Set serial interface parameters */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SITP | DFSDM_CHCFGR1_SPICKSEL); + hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.SerialInterface.Type | + hdfsdm_channel->Init.SerialInterface.SpiClock); + + /* Set analog watchdog parameters */ + hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_AWFORD | DFSDM_CHAWSCDR_AWFOSR); + hdfsdm_channel->Instance->CHAWSCDR |= (hdfsdm_channel->Init.Awd.FilterOrder | + ((hdfsdm_channel->Init.Awd.Oversampling - 1U) << DFSDM_CHAWSCDR_AWFOSR_Pos)); + + /* Set channel offset and right bit shift */ + hdfsdm_channel->Instance->CHCFGR2 &= ~(DFSDM_CHCFGR2_OFFSET | DFSDM_CHCFGR2_DTRBS); + hdfsdm_channel->Instance->CHCFGR2 |= (((uint32_t) hdfsdm_channel->Init.Offset << DFSDM_CHCFGR2_OFFSET_Pos) | + (hdfsdm_channel->Init.RightBitShift << DFSDM_CHCFGR2_DTRBS_Pos)); + + /* Enable DFSDM channel */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CHEN; + + /* Set DFSDM Channel to ready state */ + hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_READY; + + /* Store channel handle in DFSDM channel handle table */ + channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = hdfsdm_channel; + +#else + /* Check that channel has not been already initialized */ + if(a_dfsdm1ChannelHandle[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] != NULL) + { + return HAL_ERROR; + } + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + /* Reset callback pointers to the weak predefined callbacks */ + hdfsdm_channel->CkabCallback = HAL_DFSDM_ChannelCkabCallback; + hdfsdm_channel->ScdCallback = HAL_DFSDM_ChannelScdCallback; + + /* Call MSP init function */ + if(hdfsdm_channel->MspInitCallback == NULL) + { + hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit; + } + hdfsdm_channel->MspInitCallback(hdfsdm_channel); +#else + /* Call MSP init function */ + HAL_DFSDM_ChannelMspInit(hdfsdm_channel); +#endif + + /* Update the channel counter */ + v_dfsdm1ChannelCounter++; + + /* Configure output serial clock and enable global DFSDM interface only for first channel */ + if(v_dfsdm1ChannelCounter == 1U) + { + assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK(hdfsdm_channel->Init.OutputClock.Selection)); + /* Set the output serial clock source */ + DFSDM1_Channel0->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTSRC); + DFSDM1_Channel0->CHCFGR1 |= hdfsdm_channel->Init.OutputClock.Selection; + + /* Reset clock divider */ + DFSDM1_Channel0->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKOUTDIV); + if(hdfsdm_channel->Init.OutputClock.Activation == ENABLE) + { + assert_param(IS_DFSDM_CHANNEL_OUTPUT_CLOCK_DIVIDER(hdfsdm_channel->Init.OutputClock.Divider)); + /* Set the output clock divider */ + DFSDM1_Channel0->CHCFGR1 |= (uint32_t) ((hdfsdm_channel->Init.OutputClock.Divider - 1U) << + DFSDM_CHCFGR1_CKOUTDIV_Pos); + } + + /* enable the DFSDM global interface */ + DFSDM1_Channel0->CHCFGR1 |= DFSDM_CHCFGR1_DFSDMEN; + } + + /* Set channel input parameters */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_DATPACK | DFSDM_CHCFGR1_DATMPX | + DFSDM_CHCFGR1_CHINSEL); + hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.Input.Multiplexer | + hdfsdm_channel->Init.Input.DataPacking | + hdfsdm_channel->Init.Input.Pins); + + /* Set serial interface parameters */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SITP | DFSDM_CHCFGR1_SPICKSEL); + hdfsdm_channel->Instance->CHCFGR1 |= (hdfsdm_channel->Init.SerialInterface.Type | + hdfsdm_channel->Init.SerialInterface.SpiClock); + + /* Set analog watchdog parameters */ + hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_AWFORD | DFSDM_CHAWSCDR_AWFOSR); + hdfsdm_channel->Instance->CHAWSCDR |= (hdfsdm_channel->Init.Awd.FilterOrder | + ((hdfsdm_channel->Init.Awd.Oversampling - 1U) << DFSDM_CHAWSCDR_AWFOSR_Pos)); + + /* Set channel offset and right bit shift */ + hdfsdm_channel->Instance->CHCFGR2 &= ~(DFSDM_CHCFGR2_OFFSET | DFSDM_CHCFGR2_DTRBS); + hdfsdm_channel->Instance->CHCFGR2 |= (((uint32_t) hdfsdm_channel->Init.Offset << DFSDM_CHCFGR2_OFFSET_Pos) | + (hdfsdm_channel->Init.RightBitShift << DFSDM_CHCFGR2_DTRBS_Pos)); + + /* Enable DFSDM channel */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CHEN; + + /* Set DFSDM Channel to ready state */ + hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_READY; + + /* Store channel handle in DFSDM channel handle table */ + a_dfsdm1ChannelHandle[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = hdfsdm_channel; +#endif /* DFSDM2_Channel0 */ + + return HAL_OK; +} + +/** + * @brief De-initialize the DFSDM channel. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ +#if defined(DFSDM2_Channel0) + __IO uint32_t* channelCounterPtr; + DFSDM_Channel_HandleTypeDef **channelHandleTable; + DFSDM_Channel_TypeDef* channel0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check DFSDM Channel handle */ + if(hdfsdm_channel == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + channelCounterPtr = &v_dfsdm1ChannelCounter; + channelHandleTable = a_dfsdm1ChannelHandle; + channel0Instance = DFSDM1_Channel0; + } + else + { + channelCounterPtr = &v_dfsdm2ChannelCounter; + channelHandleTable = a_dfsdm2ChannelHandle; + channel0Instance = DFSDM2_Channel0; + } + + /* Check that channel has not been already deinitialized */ + if(channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] == NULL) + { + return HAL_ERROR; + } + + /* Disable the DFSDM channel */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CHEN); + + /* Update the channel counter */ + (*channelCounterPtr)--; + + /* Disable global DFSDM at deinit of last channel */ + if(*channelCounterPtr == 0U) + { + channel0Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_DFSDMEN); + } + + /* Call MSP deinit function */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + if(hdfsdm_channel->MspDeInitCallback == NULL) + { + hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit; + } + hdfsdm_channel->MspDeInitCallback(hdfsdm_channel); +#else + HAL_DFSDM_ChannelMspDeInit(hdfsdm_channel); +#endif + + /* Set DFSDM Channel in reset state */ + hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_RESET; + + /* Reset channel handle in DFSDM channel handle table */ + channelHandleTable[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = NULL; +#else + /* Check that channel has not been already deinitialized */ + if(a_dfsdm1ChannelHandle[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] == NULL) + { + return HAL_ERROR; + } + + /* Disable the DFSDM channel */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CHEN); + + /* Update the channel counter */ + v_dfsdm1ChannelCounter--; + + /* Disable global DFSDM at deinit of last channel */ + if(v_dfsdm1ChannelCounter == 0U) + { + DFSDM1_Channel0->CHCFGR1 &= ~(DFSDM_CHCFGR1_DFSDMEN); + } + + /* Call MSP deinit function */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + if(hdfsdm_channel->MspDeInitCallback == NULL) + { + hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit; + } + hdfsdm_channel->MspDeInitCallback(hdfsdm_channel); +#else + HAL_DFSDM_ChannelMspDeInit(hdfsdm_channel); +#endif + + /* Set DFSDM Channel in reset state */ + hdfsdm_channel->State = HAL_DFSDM_CHANNEL_STATE_RESET; + + /* Reset channel handle in DFSDM channel handle table */ + a_dfsdm1ChannelHandle[DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance)] = (DFSDM_Channel_HandleTypeDef *) NULL; +#endif /* defined(DFSDM2_Channel0) */ + + return HAL_OK; +} + +/** + * @brief Initialize the DFSDM channel MSP. + * @param hdfsdm_channel DFSDM channel handle. + * @retval None + */ +__weak void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_channel); + /* NOTE : This function should not be modified, when the function is needed, + the HAL_DFSDM_ChannelMspInit could be implemented in the user file. + */ +} + +/** + * @brief De-initialize the DFSDM channel MSP. + * @param hdfsdm_channel DFSDM channel handle. + * @retval None + */ +__weak void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_channel); + /* NOTE : This function should not be modified, when the function is needed, + the HAL_DFSDM_ChannelMspDeInit could be implemented in the user file. + */ +} + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/** + * @brief Register a user DFSDM channel callback + * to be used instead of the weak predefined callback. + * @param hdfsdm_channel DFSDM channel handle. + * @param CallbackID ID of the callback to be registered. + * This parameter can be one of the following values: + * @arg @ref HAL_DFSDM_CHANNEL_CKAB_CB_ID clock absence detection callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_SCD_CB_ID short circuit detection callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID MSP de-init callback ID. + * @param pCallback pointer to the callback function. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Channel_RegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID, + pDFSDM_Channel_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* update return status */ + status = HAL_ERROR; + } + else + { + if(HAL_DFSDM_CHANNEL_STATE_READY == hdfsdm_channel->State) + { + switch (CallbackID) + { + case HAL_DFSDM_CHANNEL_CKAB_CB_ID : + hdfsdm_channel->CkabCallback = pCallback; + break; + case HAL_DFSDM_CHANNEL_SCD_CB_ID : + hdfsdm_channel->ScdCallback = pCallback; + break; + case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID : + hdfsdm_channel->MspInitCallback = pCallback; + break; + case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID : + hdfsdm_channel->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_DFSDM_CHANNEL_STATE_RESET == hdfsdm_channel->State) + { + switch (CallbackID) + { + case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID : + hdfsdm_channel->MspInitCallback = pCallback; + break; + case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID : + hdfsdm_channel->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Unregister a user DFSDM channel callback. + * DFSDM channel callback is redirected to the weak predefined callback. + * @param hdfsdm_channel DFSDM channel handle. + * @param CallbackID ID of the callback to be unregistered. + * This parameter can be one of the following values: + * @arg @ref HAL_DFSDM_CHANNEL_CKAB_CB_ID clock absence detection callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_SCD_CB_ID short circuit detection callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID MSP de-init callback ID. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Channel_UnRegisterCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + HAL_DFSDM_Channel_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(HAL_DFSDM_CHANNEL_STATE_READY == hdfsdm_channel->State) + { + switch (CallbackID) + { + case HAL_DFSDM_CHANNEL_CKAB_CB_ID : + hdfsdm_channel->CkabCallback = HAL_DFSDM_ChannelCkabCallback; + break; + case HAL_DFSDM_CHANNEL_SCD_CB_ID : + hdfsdm_channel->ScdCallback = HAL_DFSDM_ChannelScdCallback; + break; + case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID : + hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit; + break; + case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID : + hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_DFSDM_CHANNEL_STATE_RESET == hdfsdm_channel->State) + { + switch (CallbackID) + { + case HAL_DFSDM_CHANNEL_MSPINIT_CB_ID : + hdfsdm_channel->MspInitCallback = HAL_DFSDM_ChannelMspInit; + break; + case HAL_DFSDM_CHANNEL_MSPDEINIT_CB_ID : + hdfsdm_channel->MspDeInitCallback = HAL_DFSDM_ChannelMspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + return status; +} +#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group2_Channel Channel operation functions + * @brief Channel operation functions + * +@verbatim + ============================================================================== + ##### Channel operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Manage clock absence detector feature. + (+) Manage short circuit detector feature. + (+) Get analog watchdog value. + (+) Modify offset value. +@endverbatim + * @{ + */ + +/** + * @brief This function allows to start clock absence detection in polling mode. + * @note Same mode has to be used for all channels. + * @note If clock is not available on this channel during 5 seconds, + * clock absence detection will not be activated and function + * will return HAL_TIMEOUT error. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart; + uint32_t channel; + +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { +#if defined (DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Clear clock absence flag */ + while((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U) + { + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Check the Timeout */ + if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT) + { + /* Set timeout status */ + status = HAL_TIMEOUT; + break; + } + } +#else + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Clear clock absence flag */ + while((((DFSDM1_Filter0->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U) + { + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Check the Timeout */ + if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT) + { + /* Set timeout status */ + status = HAL_TIMEOUT; + break; + } + } +#endif /* DFSDM2_Channel0 */ + + if(status == HAL_OK) + { + /* Start clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CKABEN; + } + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to poll for the clock absence detection. + * @param hdfsdm_channel DFSDM channel handle. + * @param Timeout Timeout value in milliseconds. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelPollForCkab(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + return HAL_ERROR; + } + else + { +#if defined(DFSDM2_Channel0) + + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait clock absence detection */ + while((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) == 0U) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + + /* Clear clock absence detection flag */ + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); +#else + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait clock absence detection */ + while((((DFSDM1_Filter0->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) == 0U) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + + /* Clear clock absence detection flag */ + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); +#endif /* defined(DFSDM2_Channel0) */ + /* Return function status */ + return HAL_OK; + } +} + +/** + * @brief This function allows to stop clock absence detection in polling mode. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { +#if defined(DFSDM2_Channel0) + + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + /* Stop clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN); + + /* Clear clock absence flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + +#else + /* Stop clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN); + + /* Clear clock absence flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); +#endif /* DFSDM2_Channel0 */ + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start clock absence detection in interrupt mode. + * @note Same mode has to be used for all channels. + * @note If clock is not available on this channel during 5 seconds, + * clock absence detection will not be activated and function + * will return HAL_TIMEOUT error. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t channel; + uint32_t tickstart; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { +#if defined(DFSDM2_Channel0) + + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Clear clock absence flag */ + while((((filter0Instance->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U) + { + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Check the Timeout */ + if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT) + { + /* Set timeout status */ + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Activate clock absence detection interrupt */ + filter0Instance->FLTCR2 |= DFSDM_FLTCR2_CKABIE; + + /* Start clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CKABEN; + } +#else + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Clear clock absence flag */ + while((((DFSDM1_Filter0->FLTISR & DFSDM_FLTISR_CKABF) >> (DFSDM_FLTISR_CKABF_Pos + channel)) & 1U) != 0U) + { + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Check the Timeout */ + if((HAL_GetTick()-tickstart) > DFSDM_CKAB_TIMEOUT) + { + /* Set timeout status */ + status = HAL_TIMEOUT; + break; + } + } + + if(status == HAL_OK) + { + /* Activate clock absence detection interrupt */ + DFSDM1_Filter0->FLTCR2 |= DFSDM_FLTCR2_CKABIE; + + /* Start clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_CKABEN; + } + +#endif /* defined(DFSDM2_Channel0) */ + } + /* Return function status */ + return status; +} + +/** + * @brief Clock absence detection callback. + * @param hdfsdm_channel DFSDM channel handle. + * @retval None + */ +__weak void HAL_DFSDM_ChannelCkabCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_channel); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_ChannelCkabCallback could be implemented in the user file + */ +} + +/** + * @brief This function allows to stop clock absence detection in interrupt mode. + * @note Interrupt will be disabled for all channels + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelCkabStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { +#if defined(DFSDM2_Channel0) + + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + /* Stop clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN); + + /* Clear clock absence flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Disable clock absence detection interrupt */ + filter0Instance->FLTCR2 &= ~(DFSDM_FLTCR2_CKABIE); +#else + + /* Stop clock absence detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_CKABEN); + + /* Clear clock absence flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Disable clock absence detection interrupt */ + DFSDM1_Filter0->FLTCR2 &= ~(DFSDM_FLTCR2_CKABIE); +#endif /* DFSDM2_Channel0 */ + } + + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start short circuit detection in polling mode. + * @note Same mode has to be used for all channels + * @param hdfsdm_channel DFSDM channel handle. + * @param Threshold Short circuit detector threshold. + * This parameter must be a number between Min_Data = 0 and Max_Data = 255. + * @param BreakSignal Break signals assigned to short circuit event. + * This parameter can be a values combination of @ref DFSDM_BreakSignals. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + uint32_t Threshold, + uint32_t BreakSignal) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + assert_param(IS_DFSDM_CHANNEL_SCD_THRESHOLD(Threshold)); + assert_param(IS_DFSDM_BREAK_SIGNALS(BreakSignal)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Configure threshold and break signals */ + hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_BKSCD | DFSDM_CHAWSCDR_SCDT); + hdfsdm_channel->Instance->CHAWSCDR |= ((BreakSignal << DFSDM_CHAWSCDR_BKSCD_Pos) | \ + Threshold); + + /* Start short circuit detection */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_SCDEN; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to poll for the short circuit detection. + * @param hdfsdm_channel DFSDM channel handle. + * @param Timeout Timeout value in milliseconds. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelPollForScd(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + return HAL_ERROR; + } + else + { + /* Get channel number from channel instance */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait short circuit detection */ + while(((filter0Instance->FLTISR & DFSDM_FLTISR_SCDF) >> (DFSDM_FLTISR_SCDF_Pos + channel)) == 0U) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + + /* Clear short circuit detection flag */ + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); + +#else + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait short circuit detection */ + while(((DFSDM1_Filter0->FLTISR & DFSDM_FLTISR_SCDF) >> (DFSDM_FLTISR_SCDF_Pos + channel)) == 0U) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + + /* Clear short circuit detection flag */ + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); +#endif /* DFSDM2_Channel0 */ + + /* Return function status */ + return HAL_OK; + } +} + +/** + * @brief This function allows to stop short circuit detection in polling mode. + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop short circuit detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SCDEN); + + /* Clear short circuit detection flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); + +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); +#else + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); +#endif /* DFSDM2_Channel0*/ + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start short circuit detection in interrupt mode. + * @note Same mode has to be used for all channels + * @param hdfsdm_channel DFSDM channel handle. + * @param Threshold Short circuit detector threshold. + * This parameter must be a number between Min_Data = 0 and Max_Data = 255. + * @param BreakSignal Break signals assigned to short circuit event. + * This parameter can be a values combination of @ref DFSDM_BreakSignals. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStart_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + uint32_t Threshold, + uint32_t BreakSignal) +{ + HAL_StatusTypeDef status = HAL_OK; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + assert_param(IS_DFSDM_CHANNEL_SCD_THRESHOLD(Threshold)); + assert_param(IS_DFSDM_BREAK_SIGNALS(BreakSignal)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + /* Activate short circuit detection interrupt */ + filter0Instance->FLTCR2 |= DFSDM_FLTCR2_SCDIE; +#else + /* Activate short circuit detection interrupt */ + DFSDM1_Filter0->FLTCR2 |= DFSDM_FLTCR2_SCDIE; +#endif /* DFSDM2_Channel0 */ + + /* Configure threshold and break signals */ + hdfsdm_channel->Instance->CHAWSCDR &= ~(DFSDM_CHAWSCDR_BKSCD | DFSDM_CHAWSCDR_SCDT); + hdfsdm_channel->Instance->CHAWSCDR |= ((BreakSignal << DFSDM_CHAWSCDR_BKSCD_Pos) | \ + Threshold); + + /* Start short circuit detection */ + hdfsdm_channel->Instance->CHCFGR1 |= DFSDM_CHCFGR1_SCDEN; + } + /* Return function status */ + return status; +} + +/** + * @brief Short circuit detection callback. + * @param hdfsdm_channel DFSDM channel handle. + * @retval None + */ +__weak void HAL_DFSDM_ChannelScdCallback(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_channel); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_ChannelScdCallback could be implemented in the user file + */ +} + +/** + * @brief This function allows to stop short circuit detection in interrupt mode. + * @note Interrupt will be disabled for all channels + * @param hdfsdm_channel DFSDM channel handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelScdStop_IT(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t channel; +#if defined(DFSDM2_Channel0) + DFSDM_Filter_TypeDef* filter0Instance; +#endif /* defined(DFSDM2_Channel0) */ + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop short circuit detection */ + hdfsdm_channel->Instance->CHCFGR1 &= ~(DFSDM_CHCFGR1_SCDEN); + + /* Clear short circuit detection flag */ + channel = DFSDM_GetChannelFromInstance(hdfsdm_channel->Instance); +#if defined(DFSDM2_Channel0) + /* Get channel counter, channel handle table and channel 0 instance */ + if(IS_DFSDM1_CHANNEL_INSTANCE(hdfsdm_channel->Instance)) + { + filter0Instance = DFSDM1_Filter0; + } + else + { + filter0Instance = DFSDM2_Filter0; + } + + filter0Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); + + /* Disable short circuit detection interrupt */ + filter0Instance->FLTCR2 &= ~(DFSDM_FLTCR2_SCDIE); +#else + DFSDM1_Filter0->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); + + /* Disable short circuit detection interrupt */ + DFSDM1_Filter0->FLTCR2 &= ~(DFSDM_FLTCR2_SCDIE); +#endif /* DFSDM2_Channel0 */ + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to get channel analog watchdog value. + * @param hdfsdm_channel DFSDM channel handle. + * @retval Channel analog watchdog value. + */ +int16_t HAL_DFSDM_ChannelGetAwdValue(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + return (int16_t) hdfsdm_channel->Instance->CHWDATAR; +} + +/** + * @brief This function allows to modify channel offset value. + * @param hdfsdm_channel DFSDM channel handle. + * @param Offset DFSDM channel offset. + * This parameter must be a number between Min_Data = -8388608 and Max_Data = 8388607. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_ChannelModifyOffset(DFSDM_Channel_HandleTypeDef *hdfsdm_channel, + int32_t Offset) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_CHANNEL_ALL_INSTANCE(hdfsdm_channel->Instance)); + assert_param(IS_DFSDM_CHANNEL_OFFSET(Offset)); + + /* Check DFSDM channel state */ + if(hdfsdm_channel->State != HAL_DFSDM_CHANNEL_STATE_READY) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Modify channel offset */ + hdfsdm_channel->Instance->CHCFGR2 &= ~(DFSDM_CHCFGR2_OFFSET); + hdfsdm_channel->Instance->CHCFGR2 |= ((uint32_t) Offset << DFSDM_CHCFGR2_OFFSET_Pos); + } + /* Return function status */ + return status; +} + +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group3_Channel Channel state function + * @brief Channel state function + * +@verbatim + ============================================================================== + ##### Channel state function ##### + ============================================================================== + [..] This section provides function allowing to: + (+) Get channel handle state. +@endverbatim + * @{ + */ + +/** + * @brief This function allows to get the current DFSDM channel handle state. + * @param hdfsdm_channel DFSDM channel handle. + * @retval DFSDM channel state. + */ +HAL_DFSDM_Channel_StateTypeDef HAL_DFSDM_ChannelGetState(const DFSDM_Channel_HandleTypeDef *hdfsdm_channel) +{ + /* Return DFSDM channel handle state */ + return hdfsdm_channel->State; +} + +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group1_Filter Filter initialization and de-initialization functions + * @brief Filter initialization and de-initialization functions + * +@verbatim + ============================================================================== + ##### Filter initialization and de-initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the DFSDM filter. + (+) De-initialize the DFSDM filter. +@endverbatim + * @{ + */ + +/** + * @brief Initialize the DFSDM filter according to the specified parameters + * in the DFSDM_FilterInitTypeDef structure and initialize the associated handle. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Check DFSDM Channel handle */ + if(hdfsdm_filter == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(IS_DFSDM_FILTER_REG_TRIGGER(hdfsdm_filter->Init.RegularParam.Trigger)); + assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.RegularParam.FastMode)); + assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.RegularParam.DmaMode)); + assert_param(IS_DFSDM_FILTER_INJ_TRIGGER(hdfsdm_filter->Init.InjectedParam.Trigger)); + assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.InjectedParam.ScanMode)); + assert_param(IS_FUNCTIONAL_STATE(hdfsdm_filter->Init.InjectedParam.DmaMode)); + assert_param(IS_DFSDM_FILTER_SINC_ORDER(hdfsdm_filter->Init.FilterParam.SincOrder)); + assert_param(IS_DFSDM_FILTER_OVS_RATIO(hdfsdm_filter->Init.FilterParam.Oversampling)); + assert_param(IS_DFSDM_FILTER_INTEGRATOR_OVS_RATIO(hdfsdm_filter->Init.FilterParam.IntOversampling)); + + /* Check parameters compatibility */ + if((hdfsdm_filter->Instance == DFSDM1_Filter0) && + ((hdfsdm_filter->Init.RegularParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER) || + (hdfsdm_filter->Init.InjectedParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER))) + { + return HAL_ERROR; + } +#if defined (DFSDM2_Channel0) + if((hdfsdm_filter->Instance == DFSDM2_Filter0) && + ((hdfsdm_filter->Init.RegularParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER) || + (hdfsdm_filter->Init.InjectedParam.Trigger == DFSDM_FILTER_SYNC_TRIGGER))) + { + return HAL_ERROR; + } +#endif /* DFSDM2_Channel0 */ + + /* Initialize DFSDM filter variables with default values */ + hdfsdm_filter->RegularContMode = DFSDM_CONTINUOUS_CONV_OFF; + hdfsdm_filter->InjectedChannelsNbr = 1U; + hdfsdm_filter->InjConvRemaining = 1U; + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_NONE; + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + /* Reset callback pointers to the weak predefined callbacks */ + hdfsdm_filter->AwdCallback = HAL_DFSDM_FilterAwdCallback; + hdfsdm_filter->RegConvCpltCallback = HAL_DFSDM_FilterRegConvCpltCallback; + hdfsdm_filter->RegConvHalfCpltCallback = HAL_DFSDM_FilterRegConvHalfCpltCallback; + hdfsdm_filter->InjConvCpltCallback = HAL_DFSDM_FilterInjConvCpltCallback; + hdfsdm_filter->InjConvHalfCpltCallback = HAL_DFSDM_FilterInjConvHalfCpltCallback; + hdfsdm_filter->ErrorCallback = HAL_DFSDM_FilterErrorCallback; + + /* Call MSP init function */ + if(hdfsdm_filter->MspInitCallback == NULL) + { + hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit; + } + hdfsdm_filter->MspInitCallback(hdfsdm_filter); +#else + /* Call MSP init function */ + HAL_DFSDM_FilterMspInit(hdfsdm_filter); +#endif + + /* Set regular parameters */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RSYNC); + if(hdfsdm_filter->Init.RegularParam.FastMode == ENABLE) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_FAST; + } + else + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_FAST); + } + + if(hdfsdm_filter->Init.RegularParam.DmaMode == ENABLE) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RDMAEN; + } + else + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RDMAEN); + } + + /* Set injected parameters */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSYNC | DFSDM_FLTCR1_JEXTEN | DFSDM_FLTCR1_JEXTSEL); + if(hdfsdm_filter->Init.InjectedParam.Trigger == DFSDM_FILTER_EXT_TRIGGER) + { + assert_param(IS_DFSDM_FILTER_EXT_TRIG(hdfsdm_filter->Init.InjectedParam.ExtTrigger)); + assert_param(IS_DFSDM_FILTER_EXT_TRIG_EDGE(hdfsdm_filter->Init.InjectedParam.ExtTriggerEdge)); + hdfsdm_filter->Instance->FLTCR1 |= (hdfsdm_filter->Init.InjectedParam.ExtTrigger); + } + + if(hdfsdm_filter->Init.InjectedParam.ScanMode == ENABLE) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSCAN; + } + else + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSCAN); + } + + if(hdfsdm_filter->Init.InjectedParam.DmaMode == ENABLE) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JDMAEN; + } + else + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JDMAEN); + } + + /* Set filter parameters */ + hdfsdm_filter->Instance->FLTFCR &= ~(DFSDM_FLTFCR_FORD | DFSDM_FLTFCR_FOSR | DFSDM_FLTFCR_IOSR); + hdfsdm_filter->Instance->FLTFCR |= (hdfsdm_filter->Init.FilterParam.SincOrder | + ((hdfsdm_filter->Init.FilterParam.Oversampling - 1U) << DFSDM_FLTFCR_FOSR_Pos) | + (hdfsdm_filter->Init.FilterParam.IntOversampling - 1U)); + + /* Store regular and injected triggers and injected scan mode*/ + hdfsdm_filter->RegularTrigger = hdfsdm_filter->Init.RegularParam.Trigger; + hdfsdm_filter->InjectedTrigger = hdfsdm_filter->Init.InjectedParam.Trigger; + hdfsdm_filter->ExtTriggerEdge = hdfsdm_filter->Init.InjectedParam.ExtTriggerEdge; + hdfsdm_filter->InjectedScanMode = hdfsdm_filter->Init.InjectedParam.ScanMode; + + /* Enable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN; + + /* Set DFSDM filter to ready state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_READY; + + return HAL_OK; +} + +/** + * @brief De-initializes the DFSDM filter. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_FilterDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Check DFSDM filter handle */ + if(hdfsdm_filter == NULL) + { + return HAL_ERROR; + } + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Disable the DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN); + + /* Call MSP deinit function */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + if(hdfsdm_filter->MspDeInitCallback == NULL) + { + hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit; + } + hdfsdm_filter->MspDeInitCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterMspDeInit(hdfsdm_filter); +#endif + + /* Set DFSDM filter in reset state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_RESET; + + return HAL_OK; +} + +/** + * @brief Initializes the DFSDM filter MSP. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the function is needed, + the HAL_DFSDM_FilterMspInit could be implemented in the user file. + */ +} + +/** + * @brief De-initializes the DFSDM filter MSP. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the function is needed, + the HAL_DFSDM_FilterMspDeInit could be implemented in the user file. + */ +} + +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) +/** + * @brief Register a user DFSDM filter callback + * to be used instead of the weak predefined callback. + * @param hdfsdm_filter DFSDM filter handle. + * @param CallbackID ID of the callback to be registered. + * This parameter can be one of the following values: + * @arg @ref HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID regular conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID half regular conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID injected conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID half injected conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_ERROR_CB_ID error callback ID. + * @arg @ref HAL_DFSDM_FILTER_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_DFSDM_FILTER_MSPDEINIT_CB_ID MSP de-init callback ID. + * @param pCallback pointer to the callback function. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID, + pDFSDM_Filter_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + else + { + if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State) + { + switch (CallbackID) + { + case HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID : + hdfsdm_filter->RegConvCpltCallback = pCallback; + break; + case HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID : + hdfsdm_filter->RegConvHalfCpltCallback = pCallback; + break; + case HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID : + hdfsdm_filter->InjConvCpltCallback = pCallback; + break; + case HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID : + hdfsdm_filter->InjConvHalfCpltCallback = pCallback; + break; + case HAL_DFSDM_FILTER_ERROR_CB_ID : + hdfsdm_filter->ErrorCallback = pCallback; + break; + case HAL_DFSDM_FILTER_MSPINIT_CB_ID : + hdfsdm_filter->MspInitCallback = pCallback; + break; + case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID : + hdfsdm_filter->MspDeInitCallback = pCallback; + break; + default : + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_DFSDM_FILTER_STATE_RESET == hdfsdm_filter->State) + { + switch (CallbackID) + { + case HAL_DFSDM_FILTER_MSPINIT_CB_ID : + hdfsdm_filter->MspInitCallback = pCallback; + break; + case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID : + hdfsdm_filter->MspDeInitCallback = pCallback; + break; + default : + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Unregister a user DFSDM filter callback. + * DFSDM filter callback is redirected to the weak predefined callback. + * @param hdfsdm_filter DFSDM filter handle. + * @param CallbackID ID of the callback to be unregistered. + * This parameter can be one of the following values: + * @arg @ref HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID regular conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID half regular conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID injected conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID half injected conversion complete callback ID. + * @arg @ref HAL_DFSDM_FILTER_ERROR_CB_ID error callback ID. + * @arg @ref HAL_DFSDM_FILTER_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_DFSDM_FILTER_MSPDEINIT_CB_ID MSP de-init callback ID. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + HAL_DFSDM_Filter_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State) + { + switch (CallbackID) + { + case HAL_DFSDM_FILTER_REGCONV_COMPLETE_CB_ID : + hdfsdm_filter->RegConvCpltCallback = HAL_DFSDM_FilterRegConvCpltCallback; + break; + case HAL_DFSDM_FILTER_REGCONV_HALFCOMPLETE_CB_ID : + hdfsdm_filter->RegConvHalfCpltCallback = HAL_DFSDM_FilterRegConvHalfCpltCallback; + break; + case HAL_DFSDM_FILTER_INJCONV_COMPLETE_CB_ID : + hdfsdm_filter->InjConvCpltCallback = HAL_DFSDM_FilterInjConvCpltCallback; + break; + case HAL_DFSDM_FILTER_INJCONV_HALFCOMPLETE_CB_ID : + hdfsdm_filter->InjConvHalfCpltCallback = HAL_DFSDM_FilterInjConvHalfCpltCallback; + break; + case HAL_DFSDM_FILTER_ERROR_CB_ID : + hdfsdm_filter->ErrorCallback = HAL_DFSDM_FilterErrorCallback; + break; + case HAL_DFSDM_FILTER_MSPINIT_CB_ID : + hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit; + break; + case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID : + hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit; + break; + default : + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if(HAL_DFSDM_FILTER_STATE_RESET == hdfsdm_filter->State) + { + switch (CallbackID) + { + case HAL_DFSDM_FILTER_MSPINIT_CB_ID : + hdfsdm_filter->MspInitCallback = HAL_DFSDM_FilterMspInit; + break; + case HAL_DFSDM_FILTER_MSPDEINIT_CB_ID : + hdfsdm_filter->MspDeInitCallback = HAL_DFSDM_FilterMspDeInit; + break; + default : + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + return status; +} + +/** + * @brief Register a user DFSDM filter analog watchdog callback + * to be used instead of the weak predefined callback. + * @param hdfsdm_filter DFSDM filter handle. + * @param pCallback pointer to the DFSDM filter analog watchdog callback function. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Filter_RegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + pDFSDM_Filter_AwdCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + else + { + if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State) + { + hdfsdm_filter->AwdCallback = pCallback; + } + else + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Unregister a user DFSDM filter analog watchdog callback. + * DFSDM filter AWD callback is redirected to the weak predefined callback. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_DFSDM_Filter_UnRegisterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(HAL_DFSDM_FILTER_STATE_READY == hdfsdm_filter->State) + { + hdfsdm_filter->AwdCallback = HAL_DFSDM_FilterAwdCallback; + } + else + { + /* update the error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + return status; +} +#endif /* USE_HAL_DFSDM_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group2_Filter Filter control functions + * @brief Filter control functions + * +@verbatim + ============================================================================== + ##### Filter control functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Select channel and enable/disable continuous mode for regular conversion. + (+) Select channels for injected conversion. +@endverbatim + * @{ + */ + +/** + * @brief This function allows to select channel and to enable/disable + * continuous mode for regular conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Channel for regular conversion. + * This parameter can be a value of @ref DFSDM_Channel_Selection. + * @param ContinuousMode Enable/disable continuous mode for regular conversion. + * This parameter can be a value of @ref DFSDM_ContinuousMode. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterConfigRegChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel, + uint32_t ContinuousMode) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(IS_DFSDM_REGULAR_CHANNEL(Channel)); + assert_param(IS_DFSDM_CONTINUOUS_MODE(ContinuousMode)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_RESET) && + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Configure channel and continuous mode for regular conversion */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RCH | DFSDM_FLTCR1_RCONT); + if(ContinuousMode == DFSDM_CONTINUOUS_CONV_ON) + { + hdfsdm_filter->Instance->FLTCR1 |= (uint32_t) (((Channel & DFSDM_MSB_MASK) << DFSDM_FLTCR1_MSB_RCH_OFFSET) | + DFSDM_FLTCR1_RCONT); + } + else + { + hdfsdm_filter->Instance->FLTCR1 |= (uint32_t) ((Channel & DFSDM_MSB_MASK) << DFSDM_FLTCR1_MSB_RCH_OFFSET); + } + /* Store continuous mode information */ + hdfsdm_filter->RegularContMode = ContinuousMode; + } + else + { + status = HAL_ERROR; + } + + /* Return function status */ + return status; +} + +/** + * @brief This function allows to select channels for injected conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Channels for injected conversion. + * This parameter can be a values combination of @ref DFSDM_Channel_Selection. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterConfigInjChannel(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(IS_DFSDM_INJECTED_CHANNEL(Channel)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_RESET) && + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Configure channel for injected conversion */ + hdfsdm_filter->Instance->FLTJCHGR = (uint32_t) (Channel & DFSDM_LSB_MASK); + /* Store number of injected channels */ + hdfsdm_filter->InjectedChannelsNbr = DFSDM_GetInjChannelsNbr(Channel); + /* Update number of injected channels remaining */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group3_Filter Filter operation functions + * @brief Filter operation functions + * +@verbatim + ============================================================================== + ##### Filter operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Start conversion of regular/injected channel. + (+) Poll for the end of regular/injected conversion. + (+) Stop conversion of regular/injected channel. + (+) Start conversion of regular/injected channel and enable interrupt. + (+) Call the callback functions at the end of regular/injected conversions. + (+) Stop conversion of regular/injected channel and disable interrupt. + (+) Start conversion of regular/injected channel and enable DMA transfer. + (+) Stop conversion of regular/injected channel and disable DMA transfer. + (+) Start analog watchdog and enable interrupt. + (+) Call the callback function when analog watchdog occurs. + (+) Stop analog watchdog and disable interrupt. + (+) Start extreme detector. + (+) Stop extreme detector. + (+) Get result of regular channel conversion. + (+) Get result of injected channel conversion. + (+) Get extreme detector maximum and minimum values. + (+) Get conversion time. + (+) Handle DFSDM interrupt request. +@endverbatim + * @{ + */ + +/** + * @brief This function allows to start regular conversion in polling mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ)) + { + /* Start regular conversion */ + DFSDM_RegConvStart(hdfsdm_filter); + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to poll for the end of regular conversion. + * @note This function should be called only if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @param Timeout Timeout value in milliseconds. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterPollForRegConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + return HAL_ERROR; + } + else + { + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait end of regular conversion */ + while((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_REOCF) != DFSDM_FLTISR_REOCF) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + /* Check if overrun occurs */ + if((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_ROVRF) == DFSDM_FLTISR_ROVRF) + { + /* Update error code and call error callback */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_REGULAR_OVERRUN; +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->ErrorCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterErrorCallback(hdfsdm_filter); +#endif + + /* Clear regular overrun flag */ + hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRROVRF; + } + /* Update DFSDM filter state only if not continuous conversion and SW trigger */ + if((hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER)) + { + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ; + } + /* Return function status */ + return HAL_OK; + } +} + +/** + * @brief This function allows to stop regular conversion in polling mode. + * @note This function should be called only if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop regular conversion */ + DFSDM_RegConvStop(hdfsdm_filter); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start regular conversion in interrupt mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ)) + { + /* Enable interrupts for regular conversions */ + hdfsdm_filter->Instance->FLTCR2 |= (DFSDM_FLTCR2_REOCIE | DFSDM_FLTCR2_ROVRIE); + + /* Start regular conversion */ + DFSDM_RegConvStart(hdfsdm_filter); + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop regular conversion in interrupt mode. + * @note This function should be called only if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Disable interrupts for regular conversions */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_REOCIE | DFSDM_FLTCR2_ROVRIE); + + /* Stop regular conversion */ + DFSDM_RegConvStop(hdfsdm_filter); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start regular conversion in DMA mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if injected conversion is ongoing. + * Please note that data on buffer will contain signed regular conversion + * value on 24 most significant bits and corresponding channel on 3 least + * significant bits. + * @param hdfsdm_filter DFSDM filter handle. + * @param pData The destination buffer address. + * @param Length The length of data to be transferred from DFSDM filter to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + int32_t *pData, + uint32_t Length) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check destination address and length */ + if((pData == NULL) || (Length == 0U)) + { + status = HAL_ERROR; + } + /* Check that DMA is enabled for regular conversion */ + else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_RDMAEN) != DFSDM_FLTCR1_RDMAEN) + { + status = HAL_ERROR; + } + /* Check parameters compatibility */ + else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->hdmaReg->Init.Mode == DMA_NORMAL) && \ + (Length != 1U)) + { + status = HAL_ERROR; + } + else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR)) + { + status = HAL_ERROR; + } + /* Check DFSDM filter state */ + else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ)) + { + /* Set callbacks on DMA handler */ + hdfsdm_filter->hdmaReg->XferCpltCallback = DFSDM_DMARegularConvCplt; + hdfsdm_filter->hdmaReg->XferErrorCallback = DFSDM_DMAError; + hdfsdm_filter->hdmaReg->XferHalfCpltCallback = (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR) ?\ + DFSDM_DMARegularHalfConvCplt : NULL; + + /* Start DMA in interrupt mode */ + if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaReg, (uint32_t)&hdfsdm_filter->Instance->FLTRDATAR, \ + (uint32_t) pData, Length) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Start regular conversion */ + DFSDM_RegConvStart(hdfsdm_filter); + } + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start regular conversion in DMA mode and to get + * only the 16 most significant bits of conversion. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if injected conversion is ongoing. + * Please note that data on buffer will contain signed 16 most significant + * bits of regular conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @param pData The destination buffer address. + * @param Length The length of data to be transferred from DFSDM filter to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + int16_t *pData, + uint32_t Length) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check destination address and length */ + if((pData == NULL) || (Length == 0U)) + { + status = HAL_ERROR; + } + /* Check that DMA is enabled for regular conversion */ + else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_RDMAEN) != DFSDM_FLTCR1_RDMAEN) + { + status = HAL_ERROR; + } + /* Check parameters compatibility */ + else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->hdmaReg->Init.Mode == DMA_NORMAL) && \ + (Length != 1U)) + { + status = HAL_ERROR; + } + else if((hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR)) + { + status = HAL_ERROR; + } + /* Check DFSDM filter state */ + else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ)) + { + /* Set callbacks on DMA handler */ + hdfsdm_filter->hdmaReg->XferCpltCallback = DFSDM_DMARegularConvCplt; + hdfsdm_filter->hdmaReg->XferErrorCallback = DFSDM_DMAError; + hdfsdm_filter->hdmaReg->XferHalfCpltCallback = (hdfsdm_filter->hdmaReg->Init.Mode == DMA_CIRCULAR) ?\ + DFSDM_DMARegularHalfConvCplt : NULL; + + /* Start DMA in interrupt mode */ + if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaReg, (uint32_t)(&hdfsdm_filter->Instance->FLTRDATAR) + 2U, \ + (uint32_t) pData, Length) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Start regular conversion */ + DFSDM_RegConvStart(hdfsdm_filter); + } + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop regular conversion in DMA mode. + * @note This function should be called only if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterRegularStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop current DMA transfer */ + if(HAL_DMA_Abort(hdfsdm_filter->hdmaReg) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Stop regular conversion */ + DFSDM_RegConvStop(hdfsdm_filter); + } + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to get regular conversion value. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Corresponding channel of regular conversion. + * @retval Regular conversion value + */ +int32_t HAL_DFSDM_FilterGetRegularValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t *Channel) +{ + uint32_t reg = 0U; + int32_t value = 0; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(Channel != NULL); + + /* Get value of data register for regular channel */ + reg = hdfsdm_filter->Instance->FLTRDATAR; + + /* Extract channel and regular conversion value */ + *Channel = (reg & DFSDM_FLTRDATAR_RDATACH); + value = ((int32_t)(reg & DFSDM_FLTRDATAR_RDATA) >> DFSDM_FLTRDATAR_RDATA_Pos); + + /* return regular conversion value */ + return value; +} + +/** + * @brief This function allows to start injected conversion in polling mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG)) + { + /* Start injected conversion */ + DFSDM_InjConvStart(hdfsdm_filter); + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to poll for the end of injected conversion. + * @note This function should be called only if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @param Timeout Timeout value in milliseconds. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterPollForInjConversion(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + return HAL_ERROR; + } + else + { + /* Get timeout */ + tickstart = HAL_GetTick(); + + /* Wait end of injected conversions */ + while((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JEOCF) != DFSDM_FLTISR_JEOCF) + { + /* Check the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if( ((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U)) + { + /* Return timeout status */ + return HAL_TIMEOUT; + } + } + } + /* Check if overrun occurs */ + if((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JOVRF) == DFSDM_FLTISR_JOVRF) + { + /* Update error code and call error callback */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INJECTED_OVERRUN; +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->ErrorCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterErrorCallback(hdfsdm_filter); +#endif + + /* Clear injected overrun flag */ + hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRJOVRF; + } + + /* Update remaining injected conversions */ + hdfsdm_filter->InjConvRemaining--; + if(hdfsdm_filter->InjConvRemaining == 0U) + { + /* Update DFSDM filter state only if trigger is software */ + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) + { + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG; + } + + /* end of injected sequence, reset the value */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + } + + /* Return function status */ + return HAL_OK; + } +} + +/** + * @brief This function allows to stop injected conversion in polling mode. + * @note This function should be called only if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop injected conversion */ + DFSDM_InjConvStop(hdfsdm_filter); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start injected conversion in interrupt mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if regular conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG)) + { + /* Enable interrupts for injected conversions */ + hdfsdm_filter->Instance->FLTCR2 |= (DFSDM_FLTCR2_JEOCIE | DFSDM_FLTCR2_JOVRIE); + + /* Start injected conversion */ + DFSDM_InjConvStart(hdfsdm_filter); + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop injected conversion in interrupt mode. + * @note This function should be called only if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Disable interrupts for injected conversions */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_JEOCIE | DFSDM_FLTCR2_JOVRIE); + + /* Stop injected conversion */ + DFSDM_InjConvStop(hdfsdm_filter); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start injected conversion in DMA mode. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if regular conversion is ongoing. + * Please note that data on buffer will contain signed injected conversion + * value on 24 most significant bits and corresponding channel on 3 least + * significant bits. + * @param hdfsdm_filter DFSDM filter handle. + * @param pData The destination buffer address. + * @param Length The length of data to be transferred from DFSDM filter to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + int32_t *pData, + uint32_t Length) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check destination address and length */ + if((pData == NULL) || (Length == 0U)) + { + status = HAL_ERROR; + } + /* Check that DMA is enabled for injected conversion */ + else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_JDMAEN) != DFSDM_FLTCR1_JDMAEN) + { + status = HAL_ERROR; + } + /* Check parameters compatibility */ + else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->hdmaInj->Init.Mode == DMA_NORMAL) && \ + (Length > hdfsdm_filter->InjConvRemaining)) + { + status = HAL_ERROR; + } + else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR)) + { + status = HAL_ERROR; + } + /* Check DFSDM filter state */ + else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG)) + { + /* Set callbacks on DMA handler */ + hdfsdm_filter->hdmaInj->XferCpltCallback = DFSDM_DMAInjectedConvCplt; + hdfsdm_filter->hdmaInj->XferErrorCallback = DFSDM_DMAError; + hdfsdm_filter->hdmaInj->XferHalfCpltCallback = (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR) ?\ + DFSDM_DMAInjectedHalfConvCplt : NULL; + + /* Start DMA in interrupt mode */ + if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaInj, (uint32_t)&hdfsdm_filter->Instance->FLTJDATAR, \ + (uint32_t) pData, Length) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Start injected conversion */ + DFSDM_InjConvStart(hdfsdm_filter); + } + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start injected conversion in DMA mode and to get + * only the 16 most significant bits of conversion. + * @note This function should be called only when DFSDM filter instance is + * in idle state or if regular conversion is ongoing. + * Please note that data on buffer will contain signed 16 most significant + * bits of injected conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @param pData The destination buffer address. + * @param Length The length of data to be transferred from DFSDM filter to memory. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedMsbStart_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + int16_t *pData, + uint32_t Length) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check destination address and length */ + if((pData == NULL) || (Length == 0U)) + { + status = HAL_ERROR; + } + /* Check that DMA is enabled for injected conversion */ + else if((hdfsdm_filter->Instance->FLTCR1 & DFSDM_FLTCR1_JDMAEN) != DFSDM_FLTCR1_JDMAEN) + { + status = HAL_ERROR; + } + /* Check parameters compatibility */ + else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->hdmaInj->Init.Mode == DMA_NORMAL) && \ + (Length > hdfsdm_filter->InjConvRemaining)) + { + status = HAL_ERROR; + } + else if((hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) && \ + (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR)) + { + status = HAL_ERROR; + } + /* Check DFSDM filter state */ + else if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG)) + { + /* Set callbacks on DMA handler */ + hdfsdm_filter->hdmaInj->XferCpltCallback = DFSDM_DMAInjectedConvCplt; + hdfsdm_filter->hdmaInj->XferErrorCallback = DFSDM_DMAError; + hdfsdm_filter->hdmaInj->XferHalfCpltCallback = (hdfsdm_filter->hdmaInj->Init.Mode == DMA_CIRCULAR) ?\ + DFSDM_DMAInjectedHalfConvCplt : NULL; + + /* Start DMA in interrupt mode */ + if(HAL_DMA_Start_IT(hdfsdm_filter->hdmaInj, (uint32_t)(&hdfsdm_filter->Instance->FLTJDATAR) + 2U, \ + (uint32_t) pData, Length) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Start injected conversion */ + DFSDM_InjConvStart(hdfsdm_filter); + } + } + else + { + status = HAL_ERROR; + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop injected conversion in DMA mode. + * @note This function should be called only if injected conversion is ongoing. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterInjectedStop_DMA(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_INJ) && \ + (hdfsdm_filter->State != HAL_DFSDM_FILTER_STATE_REG_INJ)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Stop current DMA transfer */ + if(HAL_DMA_Abort(hdfsdm_filter->hdmaInj) != HAL_OK) + { + /* Set DFSDM filter in error state */ + hdfsdm_filter->State = HAL_DFSDM_FILTER_STATE_ERROR; + status = HAL_ERROR; + } + else + { + /* Stop regular conversion */ + DFSDM_InjConvStop(hdfsdm_filter); + } + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to get injected conversion value. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Corresponding channel of injected conversion. + * @retval Injected conversion value + */ +int32_t HAL_DFSDM_FilterGetInjectedValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t *Channel) +{ + uint32_t reg = 0U; + int32_t value = 0; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(Channel != NULL); + + /* Get value of data register for injected channel */ + reg = hdfsdm_filter->Instance->FLTJDATAR; + + /* Extract channel and injected conversion value */ + *Channel = (reg & DFSDM_FLTJDATAR_JDATACH); + value = ((int32_t)(reg & DFSDM_FLTJDATAR_JDATA) >> DFSDM_FLTJDATAR_JDATA_Pos); + + /* return regular conversion value */ + return value; +} + +/** + * @brief This function allows to start filter analog watchdog in interrupt mode. + * @param hdfsdm_filter DFSDM filter handle. + * @param awdParam DFSDM filter analog watchdog parameters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterAwdStart_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + const DFSDM_Filter_AwdParamTypeDef *awdParam) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(IS_DFSDM_FILTER_AWD_DATA_SOURCE(awdParam->DataSource)); + assert_param(IS_DFSDM_INJECTED_CHANNEL(awdParam->Channel)); + assert_param(IS_DFSDM_FILTER_AWD_THRESHOLD(awdParam->HighThreshold)); + assert_param(IS_DFSDM_FILTER_AWD_THRESHOLD(awdParam->LowThreshold)); + assert_param(IS_DFSDM_BREAK_SIGNALS(awdParam->HighBreakSignal)); + assert_param(IS_DFSDM_BREAK_SIGNALS(awdParam->LowBreakSignal)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Set analog watchdog data source */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_AWFSEL); + hdfsdm_filter->Instance->FLTCR1 |= awdParam->DataSource; + + /* Set thresholds and break signals */ + hdfsdm_filter->Instance->FLTAWHTR &= ~(DFSDM_FLTAWHTR_AWHT | DFSDM_FLTAWHTR_BKAWH); + hdfsdm_filter->Instance->FLTAWHTR |= (((uint32_t) awdParam->HighThreshold << DFSDM_FLTAWHTR_AWHT_Pos) | \ + awdParam->HighBreakSignal); + hdfsdm_filter->Instance->FLTAWLTR &= ~(DFSDM_FLTAWLTR_AWLT | DFSDM_FLTAWLTR_BKAWL); + hdfsdm_filter->Instance->FLTAWLTR |= (((uint32_t) awdParam->LowThreshold << DFSDM_FLTAWLTR_AWLT_Pos) | \ + awdParam->LowBreakSignal); + + /* Set channels and interrupt for analog watchdog */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_AWDCH); + hdfsdm_filter->Instance->FLTCR2 |= (((awdParam->Channel & DFSDM_LSB_MASK) << DFSDM_FLTCR2_AWDCH_Pos) | \ + DFSDM_FLTCR2_AWDIE); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop filter analog watchdog in interrupt mode. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterAwdStop_IT(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Reset channels for analog watchdog and deactivate interrupt */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_AWDCH | DFSDM_FLTCR2_AWDIE); + + /* Clear all analog watchdog flags */ + hdfsdm_filter->Instance->FLTAWCFR = (DFSDM_FLTAWCFR_CLRAWHTF | DFSDM_FLTAWCFR_CLRAWLTF); + + /* Reset thresholds and break signals */ + hdfsdm_filter->Instance->FLTAWHTR &= ~(DFSDM_FLTAWHTR_AWHT | DFSDM_FLTAWHTR_BKAWH); + hdfsdm_filter->Instance->FLTAWLTR &= ~(DFSDM_FLTAWLTR_AWLT | DFSDM_FLTAWLTR_BKAWL); + + /* Reset analog watchdog data source */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_AWFSEL); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to start extreme detector feature. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Channels where extreme detector is enabled. + * This parameter can be a values combination of @ref DFSDM_Channel_Selection. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterExdStart(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(IS_DFSDM_INJECTED_CHANNEL(Channel)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Set channels for extreme detector */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_EXCH); + hdfsdm_filter->Instance->FLTCR2 |= ((Channel & DFSDM_LSB_MASK) << DFSDM_FLTCR2_EXCH_Pos); + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to stop extreme detector feature. + * @param hdfsdm_filter DFSDM filter handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DFSDM_FilterExdStop(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + HAL_StatusTypeDef status = HAL_OK; + __IO uint32_t reg1; + __IO uint32_t reg2; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Check DFSDM filter state */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_RESET) || \ + (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_ERROR)) + { + /* Return error status */ + status = HAL_ERROR; + } + else + { + /* Reset channels for extreme detector */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_EXCH); + + /* Clear extreme detector values */ + reg1 = hdfsdm_filter->Instance->FLTEXMAX; + reg2 = hdfsdm_filter->Instance->FLTEXMIN; + UNUSED(reg1); /* To avoid GCC warning */ + UNUSED(reg2); /* To avoid GCC warning */ + } + /* Return function status */ + return status; +} + +/** + * @brief This function allows to get extreme detector maximum value. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Corresponding channel. + * @retval Extreme detector maximum value + * This value is between Min_Data = -8388608 and Max_Data = 8388607. + */ +int32_t HAL_DFSDM_FilterGetExdMaxValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t *Channel) +{ + uint32_t reg = 0U; + int32_t value = 0; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(Channel != NULL); + + /* Get value of extreme detector maximum register */ + reg = hdfsdm_filter->Instance->FLTEXMAX; + + /* Extract channel and extreme detector maximum value */ + *Channel = (reg & DFSDM_FLTEXMAX_EXMAXCH); + value = ((int32_t)(reg & DFSDM_FLTEXMAX_EXMAX) >> DFSDM_FLTEXMAX_EXMAX_Pos); + + /* return extreme detector maximum value */ + return value; +} + +/** + * @brief This function allows to get extreme detector minimum value. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Corresponding channel. + * @retval Extreme detector minimum value + * This value is between Min_Data = -8388608 and Max_Data = 8388607. + */ +int32_t HAL_DFSDM_FilterGetExdMinValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t *Channel) +{ + uint32_t reg = 0U; + int32_t value = 0; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + assert_param(Channel != NULL); + + /* Get value of extreme detector minimum register */ + reg = hdfsdm_filter->Instance->FLTEXMIN; + + /* Extract channel and extreme detector minimum value */ + *Channel = (reg & DFSDM_FLTEXMIN_EXMINCH); + value = ((int32_t)(reg & DFSDM_FLTEXMIN_EXMIN) >> DFSDM_FLTEXMIN_EXMIN_Pos); + + /* return extreme detector minimum value */ + return value; +} + +/** + * @brief This function allows to get conversion time value. + * @param hdfsdm_filter DFSDM filter handle. + * @retval Conversion time value + * @note To get time in second, this value has to be divided by DFSDM clock frequency. + */ +uint32_t HAL_DFSDM_FilterGetConvTimeValue(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + uint32_t reg = 0U; + uint32_t value = 0U; + + /* Check parameters */ + assert_param(IS_DFSDM_FILTER_ALL_INSTANCE(hdfsdm_filter->Instance)); + + /* Get value of conversion timer register */ + reg = hdfsdm_filter->Instance->FLTCNVTIMR; + + /* Extract conversion time value */ + value = ((reg & DFSDM_FLTCNVTIMR_CNVCNT) >> DFSDM_FLTCNVTIMR_CNVCNT_Pos); + + /* return extreme detector minimum value */ + return value; +} + +/** + * @brief This function handles the DFSDM interrupts. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +void HAL_DFSDM_IRQHandler(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Check if overrun occurs during regular conversion */ + if(((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_ROVRF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_ROVRIE) != 0U)) + { + /* Clear regular overrun flag */ + hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRROVRF; + + /* Update error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_REGULAR_OVERRUN; + + /* Call error callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->ErrorCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterErrorCallback(hdfsdm_filter); +#endif + } + /* Check if overrun occurs during injected conversion */ + else if(((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JOVRF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_JOVRIE) != 0U)) + { + /* Clear injected overrun flag */ + hdfsdm_filter->Instance->FLTICR = DFSDM_FLTICR_CLRJOVRF; + + /* Update error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_INJECTED_OVERRUN; + + /* Call error callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->ErrorCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterErrorCallback(hdfsdm_filter); +#endif + } + /* Check if end of regular conversion */ + else if(((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_REOCF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_REOCIE) != 0U)) + { + /* Call regular conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->RegConvCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterRegConvCpltCallback(hdfsdm_filter); +#endif + + /* End of conversion if mode is not continuous and software trigger */ + if((hdfsdm_filter->RegularContMode == DFSDM_CONTINUOUS_CONV_OFF) && \ + (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER)) + { + /* Disable interrupts for regular conversions */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_REOCIE); + + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ; + } + } + /* Check if end of injected conversion */ + else if(((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_JEOCF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_JEOCIE) != 0U)) + { + /* Call injected conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->InjConvCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterInjConvCpltCallback(hdfsdm_filter); +#endif + + /* Update remaining injected conversions */ + hdfsdm_filter->InjConvRemaining--; + if(hdfsdm_filter->InjConvRemaining == 0U) + { + /* End of conversion if trigger is software */ + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) + { + /* Disable interrupts for injected conversions */ + hdfsdm_filter->Instance->FLTCR2 &= ~(DFSDM_FLTCR2_JEOCIE); + + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG; + } + /* end of injected sequence, reset the value */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + } + } + /* Check if analog watchdog occurs */ + else if(((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_AWDF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_AWDIE) != 0U)) + { + uint32_t reg = 0U; + uint32_t threshold = 0U; + uint32_t channel = 0U; + + /* Get channel and threshold */ + reg = hdfsdm_filter->Instance->FLTAWSR; + threshold = ((reg & DFSDM_FLTAWSR_AWLTF) != 0U) ? DFSDM_AWD_LOW_THRESHOLD : DFSDM_AWD_HIGH_THRESHOLD; + if(threshold == DFSDM_AWD_HIGH_THRESHOLD) + { + reg = reg >> DFSDM_FLTAWSR_AWHTF_Pos; + } + while((reg & 1U) == 0U) + { + channel++; + reg = reg >> 1U; + } + /* Clear analog watchdog flag */ + hdfsdm_filter->Instance->FLTAWCFR = (threshold == DFSDM_AWD_HIGH_THRESHOLD) ? \ + (1U << (DFSDM_FLTAWSR_AWHTF_Pos + channel)) : \ + (1U << channel); + + /* Call analog watchdog callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->AwdCallback(hdfsdm_filter, channel, threshold); +#else + HAL_DFSDM_FilterAwdCallback(hdfsdm_filter, channel, threshold); +#endif + } + /* Check if clock absence occurs */ + else if((hdfsdm_filter->Instance == DFSDM1_Filter0) && \ + ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_CKABF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_CKABIE) != 0U)) + { + uint32_t reg = 0U; + uint32_t channel = 0U; + + reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_CKABF) >> DFSDM_FLTISR_CKABF_Pos); + + while(channel < DFSDM1_CHANNEL_NUMBER) + { + /* Check if flag is set and corresponding channel is enabled */ + if(((reg & 1U) != 0U) && (a_dfsdm1ChannelHandle[channel] != NULL)) + { + /* Check clock absence has been enabled for this channel */ + if((a_dfsdm1ChannelHandle[channel]->Instance->CHCFGR1 & DFSDM_CHCFGR1_CKABEN) != 0U) + { + /* Clear clock absence flag */ + hdfsdm_filter->Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Call clock absence callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + a_dfsdm1ChannelHandle[channel]->CkabCallback(a_dfsdm1ChannelHandle[channel]); +#else + HAL_DFSDM_ChannelCkabCallback(a_dfsdm1ChannelHandle[channel]); +#endif + } + } + channel++; + reg = reg >> 1U; + } + } +#if defined (DFSDM2_Channel0) + /* Check if clock absence occurs */ + else if((hdfsdm_filter->Instance == DFSDM2_Filter0) && \ + ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_CKABF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_CKABIE) != 0U)) + { + uint32_t reg = 0U; + uint32_t channel = 0U; + + reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_CKABF) >> DFSDM_FLTISR_CKABF_Pos); + + while(channel < DFSDM2_CHANNEL_NUMBER) + { + /* Check if flag is set and corresponding channel is enabled */ + if(((reg & 1U) != 0U) && (a_dfsdm2ChannelHandle[channel] != NULL)) + { + /* Check clock absence has been enabled for this channel */ + if((a_dfsdm2ChannelHandle[channel]->Instance->CHCFGR1 & DFSDM_CHCFGR1_CKABEN) != 0U) + { + /* Clear clock absence flag */ + hdfsdm_filter->Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRCKABF_Pos + channel)); + + /* Call clock absence callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + a_dfsdm2ChannelHandle[channel]->CkabCallback(a_dfsdm2ChannelHandle[channel]); +#else + HAL_DFSDM_ChannelCkabCallback(a_dfsdm2ChannelHandle[channel]); +#endif + } + } + channel++; + reg = reg >> 1U; + } + } +#endif /* DFSDM2_Channel0 */ + /* Check if short circuit detection occurs */ + else if((hdfsdm_filter->Instance == DFSDM1_Filter0) && \ + ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_SCDF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_SCDIE) != 0U)) + { + uint32_t reg = 0U; + uint32_t channel = 0U; + + /* Get channel */ + reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_SCDF) >> DFSDM_FLTISR_SCDF_Pos); + while((reg & 1U) == 0U) + { + channel++; + reg = reg >> 1U; + } + + /* Clear short circuit detection flag */ + hdfsdm_filter->Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); + + /* Call short circuit detection callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + a_dfsdm1ChannelHandle[channel]->ScdCallback(a_dfsdm1ChannelHandle[channel]); +#else + HAL_DFSDM_ChannelScdCallback(a_dfsdm1ChannelHandle[channel]); +#endif + } +#if defined (DFSDM2_Channel0) + /* Check if short circuit detection occurs */ + else if((hdfsdm_filter->Instance == DFSDM2_Filter0) && \ + ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_SCDF) != 0U) && \ + ((hdfsdm_filter->Instance->FLTCR2 & DFSDM_FLTCR2_SCDIE) != 0U)) + { + uint32_t reg = 0U; + uint32_t channel = 0U; + + /* Get channel */ + reg = ((hdfsdm_filter->Instance->FLTISR & DFSDM_FLTISR_SCDF) >> DFSDM_FLTISR_SCDF_Pos); + while((reg & 1U) == 0U) + { + channel++; + reg = reg >> 1U; + } + + /* Clear short circuit detection flag */ + hdfsdm_filter->Instance->FLTICR = (1U << (DFSDM_FLTICR_CLRSCDF_Pos + channel)); + + /* Call short circuit detection callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + a_dfsdm2ChannelHandle[channel]->ScdCallback(a_dfsdm2ChannelHandle[channel]); +#else + HAL_DFSDM_ChannelScdCallback(a_dfsdm2ChannelHandle[channel]); +#endif + } +#endif /* DFSDM2_Channel0 */ +} + +/** + * @brief Regular conversion complete callback. + * @note In interrupt mode, user has to read conversion value in this function + * using HAL_DFSDM_FilterGetRegularValue. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterRegConvCpltCallback could be implemented in the user file. + */ +} + +/** + * @brief Half regular conversion complete callback. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterRegConvHalfCpltCallback could be implemented in the user file. + */ +} + +/** + * @brief Injected conversion complete callback. + * @note In interrupt mode, user has to read conversion value in this function + * using HAL_DFSDM_FilterGetInjectedValue. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterInjConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterInjConvCpltCallback could be implemented in the user file. + */ +} + +/** + * @brief Half injected conversion complete callback. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterInjConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterInjConvHalfCpltCallback could be implemented in the user file. + */ +} + +/** + * @brief Filter analog watchdog callback. + * @param hdfsdm_filter DFSDM filter handle. + * @param Channel Corresponding channel. + * @param Threshold Low or high threshold has been reached. + * @retval None + */ +__weak void HAL_DFSDM_FilterAwdCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter, + uint32_t Channel, uint32_t Threshold) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + UNUSED(Channel); + UNUSED(Threshold); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterAwdCallback could be implemented in the user file. + */ +} + +/** + * @brief Error callback. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +__weak void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdfsdm_filter); + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_DFSDM_FilterErrorCallback could be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group4_Filter Filter state functions + * @brief Filter state functions + * +@verbatim + ============================================================================== + ##### Filter state functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Get the DFSDM filter state. + (+) Get the DFSDM filter error. +@endverbatim + * @{ + */ + +/** + * @brief This function allows to get the current DFSDM filter handle state. + * @param hdfsdm_filter DFSDM filter handle. + * @retval DFSDM filter state. + */ +HAL_DFSDM_Filter_StateTypeDef HAL_DFSDM_FilterGetState(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + /* Return DFSDM filter handle state */ + return hdfsdm_filter->State; +} + +/** + * @brief This function allows to get the current DFSDM filter error. + * @param hdfsdm_filter DFSDM filter handle. + * @retval DFSDM filter error code. + */ +uint32_t HAL_DFSDM_FilterGetError(const DFSDM_Filter_HandleTypeDef *hdfsdm_filter) +{ + return hdfsdm_filter->ErrorCode; +} + +/** + * @} + */ + +/** @defgroup DFSDM_Exported_Functions_Group5_Filter MultiChannel operation functions + * @brief Filter state functions + * +@verbatim + ============================================================================== + ##### Filter MultiChannel operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Control the DFSDM Multi channel delay block +@endverbatim + * @{ + */ +#if defined(SYSCFG_MCHDLYCR_BSCKSEL) +/** + * @brief Select the DFSDM2 as clock source for the bitstream clock. + * @note The SYSCFG clock marco __HAL_RCC_SYSCFG_CLK_ENABLE() must be called + * before HAL_DFSDM_BitstreamClock_Start() + */ +void HAL_DFSDM_BitstreamClock_Start(void) +{ + uint32_t tmp = 0; + + tmp = SYSCFG->MCHDLYCR; + tmp = (tmp &(~SYSCFG_MCHDLYCR_BSCKSEL)); + + SYSCFG->MCHDLYCR = (tmp|SYSCFG_MCHDLYCR_BSCKSEL); +} + +/** + * @brief Stop the DFSDM2 as clock source for the bitstream clock. + * @note The SYSCFG clock marco __HAL_RCC_SYSCFG_CLK_ENABLE() must be called + * before HAL_DFSDM_BitstreamClock_Stop() + * @retval None + */ +void HAL_DFSDM_BitstreamClock_Stop(void) +{ + uint32_t tmp = 0U; + + tmp = SYSCFG->MCHDLYCR; + tmp = (tmp &(~SYSCFG_MCHDLYCR_BSCKSEL)); + + SYSCFG->MCHDLYCR = tmp; +} + +/** + * @brief Disable Delay Clock for DFSDM1/2. + * @param MCHDLY HAL_MCHDLY_CLOCK_DFSDM2. + * HAL_MCHDLY_CLOCK_DFSDM1. + * @note The SYSCFG clock marco __HAL_RCC_SYSCFG_CLK_ENABLE() must be called + * before HAL_DFSDM_DisableDelayClock() + * @retval None + */ +void HAL_DFSDM_DisableDelayClock(uint32_t MCHDLY) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DELAY_CLOCK(MCHDLY)); + + tmp = SYSCFG->MCHDLYCR; + if(MCHDLY == HAL_MCHDLY_CLOCK_DFSDM2) + { + tmp = tmp &(~SYSCFG_MCHDLYCR_MCHDLY2EN); + } + else + { + tmp = tmp &(~SYSCFG_MCHDLYCR_MCHDLY1EN); + } + + SYSCFG->MCHDLYCR = tmp; +} + +/** + * @brief Enable Delay Clock for DFSDM1/2. + * @param MCHDLY HAL_MCHDLY_CLOCK_DFSDM2. + * HAL_MCHDLY_CLOCK_DFSDM1. + * @note The SYSCFG clock marco __HAL_RCC_SYSCFG_CLK_ENABLE() must be called + * before HAL_DFSDM_EnableDelayClock() + * @retval None + */ +void HAL_DFSDM_EnableDelayClock(uint32_t MCHDLY) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DELAY_CLOCK(MCHDLY)); + + tmp = SYSCFG->MCHDLYCR; + tmp = tmp & ~MCHDLY; + + SYSCFG->MCHDLYCR = (tmp|MCHDLY); +} + +/** + * @brief Select the source for CKin signals for DFSDM1/2. + * @param source DFSDM2_CKIN_PAD. + * DFSDM2_CKIN_DM. + * DFSDM1_CKIN_PAD. + * DFSDM1_CKIN_DM. + * @retval None + */ +void HAL_DFSDM_ClockIn_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_CLOCKIN_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + if((source == HAL_DFSDM2_CKIN_PAD) || (source == HAL_DFSDM2_CKIN_DM)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CFG); + + if(source == HAL_DFSDM2_CKIN_PAD) + { + source = 0x000000U; + } + } + else + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1CFG); + } + + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Select the source for CKOut signals for DFSDM1/2. + * @param source: DFSDM2_CKOUT_DFSDM2. + * DFSDM2_CKOUT_M27. + * DFSDM1_CKOUT_DFSDM1. + * DFSDM1_CKOUT_M27. + * @retval None + */ +void HAL_DFSDM_ClockOut_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_CLOCKOUT_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + if((source == HAL_DFSDM2_CKOUT_DFSDM2) || (source == HAL_DFSDM2_CKOUT_M27)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CKOSEL); + + if(source == HAL_DFSDM2_CKOUT_DFSDM2) + { + source = 0x000U; + } + } + else + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1CKOSEL); + } + + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Select the source for DataIn0 signals for DFSDM1/2. + * @param source DATAIN0_DFSDM2_PAD. + * DATAIN0_DFSDM2_DATAIN1. + * DATAIN0_DFSDM1_PAD. + * DATAIN0_DFSDM1_DATAIN1. + * @retval None + */ +void HAL_DFSDM_DataIn0_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DATAIN0_SRC_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + if((source == HAL_DATAIN0_DFSDM2_PAD)|| (source == HAL_DATAIN0_DFSDM2_DATAIN1)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2D0SEL); + if(source == HAL_DATAIN0_DFSDM2_PAD) + { + source = 0x00000U; + } + } + else + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1D0SEL); + } + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Select the source for DataIn2 signals for DFSDM1/2. + * @param source DATAIN2_DFSDM2_PAD. + * DATAIN2_DFSDM2_DATAIN3. + * DATAIN2_DFSDM1_PAD. + * DATAIN2_DFSDM1_DATAIN3. + * @retval None + */ +void HAL_DFSDM_DataIn2_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DATAIN2_SRC_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + if((source == HAL_DATAIN2_DFSDM2_PAD)|| (source == HAL_DATAIN2_DFSDM2_DATAIN3)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2D2SEL); + if (source == HAL_DATAIN2_DFSDM2_PAD) + { + source = 0x0000U; + } + } + else + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1D2SEL); + } + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Select the source for DataIn4 signals for DFSDM2. + * @param source DATAIN4_DFSDM2_PAD. + * DATAIN4_DFSDM2_DATAIN5 + * @retval None + */ +void HAL_DFSDM_DataIn4_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DATAIN4_SRC_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2D4SEL); + + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Select the source for DataIn6 signals for DFSDM2. + * @param source DATAIN6_DFSDM2_PAD. + * DATAIN6_DFSDM2_DATAIN7. + * @retval None + */ +void HAL_DFSDM_DataIn6_SourceSelection(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_DATAIN6_SRC_SELECTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2D6SEL); + + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Configure the distribution of the bitstream clock gated from TIM4_OC + * for DFSDM1 or TIM3_OC for DFSDM2 + * @param source DFSDM1_CLKIN0_TIM4OC2 + * DFSDM1_CLKIN2_TIM4OC2 + * DFSDM1_CLKIN1_TIM4OC1 + * DFSDM1_CLKIN3_TIM4OC1 + * DFSDM2_CLKIN0_TIM3OC4 + * DFSDM2_CLKIN4_TIM3OC4 + * DFSDM2_CLKIN1_TIM3OC3 + * DFSDM2_CLKIN5_TIM3OC3 + * DFSDM2_CLKIN2_TIM3OC2 + * DFSDM2_CLKIN6_TIM3OC2 + * DFSDM2_CLKIN3_TIM3OC1 + * DFSDM2_CLKIN7_TIM3OC1 + * @retval None + */ +void HAL_DFSDM_BitStreamClkDistribution_Config(uint32_t source) +{ + uint32_t tmp = 0U; + + assert_param(IS_DFSDM_BITSTREM_CLK_DISTRIBUTION(source)); + + tmp = SYSCFG->MCHDLYCR; + + if ((source == HAL_DFSDM1_CLKIN0_TIM4OC2) || (source == HAL_DFSDM1_CLKIN2_TIM4OC2)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1CK02SEL); + } + else if ((source == HAL_DFSDM1_CLKIN1_TIM4OC1) || (source == HAL_DFSDM1_CLKIN3_TIM4OC1)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM1CK13SEL); + } + else if ((source == HAL_DFSDM2_CLKIN0_TIM3OC4) || (source == HAL_DFSDM2_CLKIN4_TIM3OC4)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CK04SEL); + } + else if ((source == HAL_DFSDM2_CLKIN1_TIM3OC3) || (source == HAL_DFSDM2_CLKIN5_TIM3OC3)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CK15SEL); + + }else if ((source == HAL_DFSDM2_CLKIN2_TIM3OC2) || (source == HAL_DFSDM2_CLKIN6_TIM3OC2)) + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CK26SEL); + } + else + { + tmp = (tmp & ~SYSCFG_MCHDLYCR_DFSDM2CK37SEL); + } + + if((source == HAL_DFSDM1_CLKIN0_TIM4OC2) ||(source == HAL_DFSDM1_CLKIN1_TIM4OC1)|| + (source == HAL_DFSDM2_CLKIN0_TIM3OC4) ||(source == HAL_DFSDM2_CLKIN1_TIM3OC3)|| + (source == HAL_DFSDM2_CLKIN2_TIM3OC2) ||(source == HAL_DFSDM2_CLKIN3_TIM3OC1)) + { + source = 0x0000U; + } + + SYSCFG->MCHDLYCR = (source|tmp); +} + +/** + * @brief Configure multi channel delay block: Use DFSDM2 audio clock source as input + * clock for DFSDM1 and DFSDM2 filters to Synchronize DFSDMx filters. + * Set the path of the DFSDM2 clock output (dfsdm2_ckout) to the + * DFSDM1/2 CkInx and data inputs channels by configuring following MCHDLY muxes + * or demuxes: M1, M2, M3, M4, M5, M6, M7, M8, DM1, DM2, DM3, DM4, DM5, DM6, + * M9, M10, M11, M12, M13, M14, M15, M16, M17, M18, M19, M20 based on the + * contains of the DFSDM_MultiChannelConfigTypeDef structure + * @param mchdlystruct Structure of multi channel configuration + * @retval None + * @note The SYSCFG clock marco __HAL_RCC_SYSCFG_CLK_ENABLE() must be called + * before HAL_DFSDM_ConfigMultiChannelDelay() + * @note The HAL_DFSDM_ConfigMultiChannelDelay() function clears the SYSCFG-MCHDLYCR + * register before setting the new configuration. + */ +void HAL_DFSDM_ConfigMultiChannelDelay(DFSDM_MultiChannelConfigTypeDef* mchdlystruct) +{ + uint32_t mchdlyreg = 0U; + + assert_param(IS_DFSDM_DFSDM1_CLKOUT(mchdlystruct->DFSDM1ClockOut)); + assert_param(IS_DFSDM_DFSDM2_CLKOUT(mchdlystruct->DFSDM2ClockOut)); + assert_param(IS_DFSDM_DFSDM1_CLKIN(mchdlystruct->DFSDM1ClockIn)); + assert_param(IS_DFSDM_DFSDM2_CLKIN(mchdlystruct->DFSDM2ClockIn)); + assert_param(IS_DFSDM_DFSDM1_BIT_CLK((mchdlystruct->DFSDM1BitClkDistribution))); + assert_param(IS_DFSDM_DFSDM2_BIT_CLK(mchdlystruct->DFSDM2BitClkDistribution)); + assert_param(IS_DFSDM_DFSDM1_DATA_DISTRIBUTION(mchdlystruct->DFSDM1DataDistribution)); + assert_param(IS_DFSDM_DFSDM2_DATA_DISTRIBUTION(mchdlystruct->DFSDM2DataDistribution)); + + mchdlyreg = (SYSCFG->MCHDLYCR & 0x80103U); + + SYSCFG->MCHDLYCR = (mchdlyreg |(mchdlystruct->DFSDM1ClockOut)|(mchdlystruct->DFSDM2ClockOut)| + (mchdlystruct->DFSDM1ClockIn)|(mchdlystruct->DFSDM2ClockIn)| + (mchdlystruct->DFSDM1BitClkDistribution)| (mchdlystruct->DFSDM2BitClkDistribution)| + (mchdlystruct->DFSDM1DataDistribution)| (mchdlystruct->DFSDM2DataDistribution)); + +} +#endif /* SYSCFG_MCHDLYCR_BSCKSEL */ +/** + * @} + */ +/** + * @} + */ +/* End of exported functions -------------------------------------------------*/ + +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup DFSDM_Private_Functions DFSDM Private Functions + * @{ + */ + +/** + * @brief DMA half transfer complete callback for regular conversion. + * @param hdma DMA handle. + * @retval None + */ +static void DFSDM_DMARegularHalfConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Get DFSDM filter handle */ + DFSDM_Filter_HandleTypeDef* hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent; + + /* Call regular half conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->RegConvHalfCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterRegConvHalfCpltCallback(hdfsdm_filter); +#endif +} + +/** + * @brief DMA transfer complete callback for regular conversion. + * @param hdma DMA handle. + * @retval None + */ +static void DFSDM_DMARegularConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Get DFSDM filter handle */ + DFSDM_Filter_HandleTypeDef* hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent; + + /* Call regular conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->RegConvCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterRegConvCpltCallback(hdfsdm_filter); +#endif +} + +/** + * @brief DMA half transfer complete callback for injected conversion. + * @param hdma DMA handle. + * @retval None + */ +static void DFSDM_DMAInjectedHalfConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Get DFSDM filter handle */ + DFSDM_Filter_HandleTypeDef* hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent; + + /* Call injected half conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->InjConvHalfCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterInjConvHalfCpltCallback(hdfsdm_filter); +#endif +} + +/** + * @brief DMA transfer complete callback for injected conversion. + * @param hdma DMA handle. + * @retval None + */ +static void DFSDM_DMAInjectedConvCplt(DMA_HandleTypeDef *hdma) +{ + /* Get DFSDM filter handle */ + DFSDM_Filter_HandleTypeDef* hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent; + + /* Call injected conversion complete callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->InjConvCpltCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterInjConvCpltCallback(hdfsdm_filter); +#endif +} + +/** + * @brief DMA error callback. + * @param hdma DMA handle. + * @retval None + */ +static void DFSDM_DMAError(DMA_HandleTypeDef *hdma) +{ + /* Get DFSDM filter handle */ + DFSDM_Filter_HandleTypeDef* hdfsdm_filter = (DFSDM_Filter_HandleTypeDef*) ((DMA_HandleTypeDef*)hdma)->Parent; + + /* Update error code */ + hdfsdm_filter->ErrorCode = DFSDM_FILTER_ERROR_DMA; + + /* Call error callback */ +#if (USE_HAL_DFSDM_REGISTER_CALLBACKS == 1) + hdfsdm_filter->ErrorCallback(hdfsdm_filter); +#else + HAL_DFSDM_FilterErrorCallback(hdfsdm_filter); +#endif +} + +/** + * @brief This function allows to get the number of injected channels. + * @param Channels bitfield of injected channels. + * @retval Number of injected channels. + */ +static uint32_t DFSDM_GetInjChannelsNbr(uint32_t Channels) +{ + uint32_t nbChannels = 0U; + uint32_t tmp; + + /* Get the number of channels from bitfield */ + tmp = (uint32_t) (Channels & DFSDM_LSB_MASK); + while(tmp != 0U) + { + if((tmp & 1U) != 0U) + { + nbChannels++; + } + tmp = (uint32_t) (tmp >> 1U); + } + return nbChannels; +} + +/** + * @brief This function allows to get the channel number from channel instance. + * @param Instance DFSDM channel instance. + * @retval Channel number. + */ +static uint32_t DFSDM_GetChannelFromInstance(const DFSDM_Channel_TypeDef *Instance) +{ + uint32_t channel; + + /* Get channel from instance */ +#if defined(DFSDM2_Channel0) + if((Instance == DFSDM1_Channel0) || (Instance == DFSDM2_Channel0)) + { + channel = 0U; + } + else if((Instance == DFSDM1_Channel1) || (Instance == DFSDM2_Channel1)) + { + channel = 1U; + } + else if((Instance == DFSDM1_Channel2) || (Instance == DFSDM2_Channel2)) + { + channel = 2U; + } + else if((Instance == DFSDM1_Channel3) || (Instance == DFSDM2_Channel3)) + { + channel = 3U; + } + else if(Instance == DFSDM2_Channel4) + { + channel = 4U; + } + else if(Instance == DFSDM2_Channel5) + { + channel = 5U; + } + else if(Instance == DFSDM2_Channel6) + { + channel = 6U; + } + else /* DFSDM2_Channel7 */ + { + channel = 7U; + } + +#else + if(Instance == DFSDM1_Channel0) + { + channel = 0U; + } + else if(Instance == DFSDM1_Channel1) + { + channel = 1U; + } + else if(Instance == DFSDM1_Channel2) + { + channel = 2U; + } + else /* DFSDM1_Channel3 */ + { + channel = 3U; + } +#endif /* defined(DFSDM2_Channel0) */ + + return channel; +} + +/** + * @brief This function allows to really start regular conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +static void DFSDM_RegConvStart(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) +{ + /* Check regular trigger */ + if(hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER) + { + /* Software start of regular conversion */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART; + } + else /* synchronous trigger */ + { + /* Disable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN); + + /* Set RSYNC bit in DFSDM_FLTCR1 register */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSYNC; + + /* Enable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN; + + /* If injected conversion was in progress, restart it */ + if(hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) + { + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART; + } + /* Update remaining injected conversions */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + } + } + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) ? \ + HAL_DFSDM_FILTER_STATE_REG : HAL_DFSDM_FILTER_STATE_REG_INJ; +} + +/** + * @brief This function allows to really stop regular conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +static void DFSDM_RegConvStop(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) +{ + /* Disable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN); + + /* If regular trigger was synchronous, reset RSYNC bit in DFSDM_FLTCR1 register */ + if(hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SYNC_TRIGGER) + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_RSYNC); + } + + /* Enable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN; + + /* If injected conversion was in progress, restart it */ + if(hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG_INJ) + { + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART; + } + /* Update remaining injected conversions */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + } + + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_INJ; +} + +/** + * @brief This function allows to really start injected conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +static void DFSDM_InjConvStart(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) +{ + /* Check injected trigger */ + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SW_TRIGGER) + { + /* Software start of injected conversion */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSWSTART; + } + else /* external or synchronous trigger */ + { + /* Disable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN); + + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SYNC_TRIGGER) + { + /* Set JSYNC bit in DFSDM_FLTCR1 register */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_JSYNC; + } + else /* external trigger */ + { + /* Set JEXTEN[1:0] bits in DFSDM_FLTCR1 register */ + hdfsdm_filter->Instance->FLTCR1 |= hdfsdm_filter->ExtTriggerEdge; + } + + /* Enable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN; + + /* If regular conversion was in progress, restart it */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG) && \ + (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER)) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART; + } + } + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_READY) ? \ + HAL_DFSDM_FILTER_STATE_INJ : HAL_DFSDM_FILTER_STATE_REG_INJ; +} + +/** + * @brief This function allows to really stop injected conversion. + * @param hdfsdm_filter DFSDM filter handle. + * @retval None + */ +static void DFSDM_InjConvStop(DFSDM_Filter_HandleTypeDef* hdfsdm_filter) +{ + /* Disable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_DFEN); + + /* If injected trigger was synchronous, reset JSYNC bit in DFSDM_FLTCR1 register */ + if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_SYNC_TRIGGER) + { + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JSYNC); + } + else if(hdfsdm_filter->InjectedTrigger == DFSDM_FILTER_EXT_TRIGGER) + { + /* Reset JEXTEN[1:0] bits in DFSDM_FLTCR1 register */ + hdfsdm_filter->Instance->FLTCR1 &= ~(DFSDM_FLTCR1_JEXTEN); + } + + else + { + /* Nothing to do */ + } + /* Enable DFSDM filter */ + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_DFEN; + + /* If regular conversion was in progress, restart it */ + if((hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_REG_INJ) && \ + (hdfsdm_filter->RegularTrigger == DFSDM_FILTER_SW_TRIGGER)) + { + hdfsdm_filter->Instance->FLTCR1 |= DFSDM_FLTCR1_RSWSTART; + } + + /* Update remaining injected conversions */ + hdfsdm_filter->InjConvRemaining = (hdfsdm_filter->InjectedScanMode == ENABLE) ? \ + hdfsdm_filter->InjectedChannelsNbr : 1U; + + /* Update DFSDM filter state */ + hdfsdm_filter->State = (hdfsdm_filter->State == HAL_DFSDM_FILTER_STATE_INJ) ? \ + HAL_DFSDM_FILTER_STATE_READY : HAL_DFSDM_FILTER_STATE_REG; +} +/** + * @} + */ +/* End of private functions --------------------------------------------------*/ + +/** + * @} + */ +#endif /* STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */ +#endif /* HAL_DFSDM_MODULE_ENABLED */ +/** + * @} + */ diff --git a/libs/hal/stm32f4xx_hal_dma.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c similarity index 100% rename from libs/hal/stm32f4xx_hal_dma.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c new file mode 100644 index 0000000..4cfac40 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma2d.c @@ -0,0 +1,2126 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dma2d.c + * @author MCD Application Team + * @brief DMA2D HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the DMA2D peripheral: + * + 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 ##### + ============================================================================== + [..] + (#) Program the required configuration through the following parameters: + the transfer mode, the output color mode and the output offset using + HAL_DMA2D_Init() function. + + (#) Program the required configuration through the following parameters: + the input color mode, the input color, the input alpha value, the alpha mode, + the red/blue swap mode, the inverted alpha mode and the input offset using + HAL_DMA2D_ConfigLayer() function for foreground or/and background layer. + + *** Polling mode IO operation *** + ================================= + [..] + (#) Configure pdata parameter (explained hereafter), destination and data length + and enable the transfer using HAL_DMA2D_Start(). + (#) Wait for end of transfer using HAL_DMA2D_PollForTransfer(), at this stage + user can specify the value of timeout according to his end application. + + *** Interrupt mode IO operation *** + =================================== + [..] + (#) Configure pdata parameter, destination and data length and enable + the transfer using HAL_DMA2D_Start_IT(). + (#) Use HAL_DMA2D_IRQHandler() called under DMA2D_IRQHandler() interrupt subroutine. + (#) At the end of data transfer HAL_DMA2D_IRQHandler() function is executed and user can + add his own function by customization of function pointer XferCpltCallback (member + of DMA2D handle structure). + (#) In case of error, the HAL_DMA2D_IRQHandler() function calls the callback + XferErrorCallback. + + -@- In Register-to-Memory transfer mode, pdata parameter is the register + color, in Memory-to-memory or Memory-to-Memory with pixel format + conversion pdata is the source address. + + -@- Configure the foreground source address, the background source address, + the destination and data length then Enable the transfer using + HAL_DMA2D_BlendingStart() in polling mode and HAL_DMA2D_BlendingStart_IT() + in interrupt mode. + + -@- HAL_DMA2D_BlendingStart() and HAL_DMA2D_BlendingStart_IT() functions + are used if the memory to memory with blending transfer mode is selected. + + (#) Optionally, configure and enable the CLUT using HAL_DMA2D_CLUTLoad() in polling + mode or HAL_DMA2D_CLUTLoad_IT() in interrupt mode. + + (#) Optionally, configure the line watermark in using the API HAL_DMA2D_ProgramLineEvent(). + + (#) Optionally, configure the dead time value in the AHB clock cycle inserted between two + consecutive accesses on the AHB master port in using the API HAL_DMA2D_ConfigDeadTime() + and enable/disable the functionality with the APIs HAL_DMA2D_EnableDeadTime() or + HAL_DMA2D_DisableDeadTime(). + + (#) The transfer can be suspended, resumed and aborted using the following + functions: HAL_DMA2D_Suspend(), HAL_DMA2D_Resume(), HAL_DMA2D_Abort(). + + (#) The CLUT loading can be suspended, resumed and aborted using the following + functions: HAL_DMA2D_CLUTLoading_Suspend(), HAL_DMA2D_CLUTLoading_Resume(), + HAL_DMA2D_CLUTLoading_Abort(). + + (#) To control the DMA2D state, use the following function: HAL_DMA2D_GetState(). + + (#) To read the DMA2D error code, use the following function: HAL_DMA2D_GetError(). + + *** DMA2D HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in DMA2D HAL driver : + + (+) __HAL_DMA2D_ENABLE: Enable the DMA2D peripheral. + (+) __HAL_DMA2D_GET_FLAG: Get the DMA2D pending flags. + (+) __HAL_DMA2D_CLEAR_FLAG: Clear the DMA2D pending flags. + (+) __HAL_DMA2D_ENABLE_IT: Enable the specified DMA2D interrupts. + (+) __HAL_DMA2D_DISABLE_IT: Disable the specified DMA2D interrupts. + (+) __HAL_DMA2D_GET_IT_SOURCE: Check whether the specified DMA2D interrupt is enabled or not. + + *** Callback registration *** + =================================== + [..] + (#) The compilation define USE_HAL_DMA2D_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use function @ref HAL_DMA2D_RegisterCallback() to register a user callback. + + (#) Function @ref HAL_DMA2D_RegisterCallback() allows to register following callbacks: + (+) XferCpltCallback : callback for transfer complete. + (+) XferErrorCallback : callback for transfer error. + (+) LineEventCallback : callback for line event. + (+) CLUTLoadingCpltCallback : callback for CLUT loading completion. + (+) MspInitCallback : DMA2D MspInit. + (+) MspDeInitCallback : DMA2D MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + (#) Use function @ref HAL_DMA2D_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + @ref HAL_DMA2D_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) XferCpltCallback : callback for transfer complete. + (+) XferErrorCallback : callback for transfer error. + (+) LineEventCallback : callback for line event. + (+) CLUTLoadingCpltCallback : callback for CLUT loading completion. + (+) MspInitCallback : DMA2D MspInit. + (+) MspDeInitCallback : DMA2D MspDeInit. + + (#) By default, after the @ref HAL_DMA2D_Init and if the state is HAL_DMA2D_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions: + examples @ref HAL_DMA2D_LineEventCallback(), @ref HAL_DMA2D_CLUTLoadingCpltCallback() + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the @ref HAL_DMA2D_Init + and @ref HAL_DMA2D_DeInit only when these callbacks are null (not registered beforehand) + If not, MspInit or MspDeInit are not null, the @ref HAL_DMA2D_Init and @ref HAL_DMA2D_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + Exception as well for Transfer Completion and Transfer Error callbacks that are not defined + as weak (surcharged) functions. They must be defined by the user to be resorted to. + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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 @ref HAL_DMA2D_RegisterCallback before calling @ref HAL_DMA2D_DeInit + or @ref HAL_DMA2D_Init function. + + When The compilation define USE_HAL_DMA2D_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + [..] + (@) You can refer to the DMA2D HAL driver header file for more useful macros + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#ifdef HAL_DMA2D_MODULE_ENABLED +#if defined (DMA2D) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup DMA2D DMA2D + * @brief DMA2D HAL module driver + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup DMA2D_Private_Constants DMA2D Private Constants + * @{ + */ + +/** @defgroup DMA2D_TimeOut DMA2D Time Out + * @{ + */ +#define DMA2D_TIMEOUT_ABORT (1000U) /*!< 1s */ +#define DMA2D_TIMEOUT_SUSPEND (1000U) /*!< 1s */ +/** + * @} + */ + +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup DMA2D_Private_Functions DMA2D Private Functions + * @{ + */ +static void DMA2D_SetConfig(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height); +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup DMA2D_Exported_Functions DMA2D Exported Functions + * @{ + */ + +/** @defgroup DMA2D_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the DMA2D + (+) De-initialize the DMA2D + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the DMA2D according to the specified + * parameters in the DMA2D_InitTypeDef and create the associated handle. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d) +{ + /* Check the DMA2D peripheral state */ + if (hdma2d == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance)); + assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode)); + assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode)); + assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset)); + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) + if (hdma2d->State == HAL_DMA2D_STATE_RESET) + { + /* Reset Callback pointers in HAL_DMA2D_STATE_RESET only */ + hdma2d->LineEventCallback = HAL_DMA2D_LineEventCallback; + hdma2d->CLUTLoadingCpltCallback = HAL_DMA2D_CLUTLoadingCpltCallback; + if (hdma2d->MspInitCallback == NULL) + { + hdma2d->MspInitCallback = HAL_DMA2D_MspInit; + } + + /* Init the low level hardware */ + hdma2d->MspInitCallback(hdma2d); + } +#else + if (hdma2d->State == HAL_DMA2D_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hdma2d->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_DMA2D_MspInit(hdma2d); + } +#endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */ + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* DMA2D CR register configuration -------------------------------------------*/ + MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE, hdma2d->Init.Mode); + + /* DMA2D OPFCCR register configuration ---------------------------------------*/ + MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM, hdma2d->Init.ColorMode); + + /* DMA2D OOR register configuration ------------------------------------------*/ + MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset); + + + /* Update error code */ + hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE; + + /* Initialize the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Deinitializes the DMA2D peripheral registers to their default reset + * values. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval None + */ + +HAL_StatusTypeDef HAL_DMA2D_DeInit(DMA2D_HandleTypeDef *hdma2d) +{ + + /* Check the DMA2D peripheral state */ + if (hdma2d == NULL) + { + return HAL_ERROR; + } + + /* Before aborting any DMA2D transfer or CLUT loading, check + first whether or not DMA2D clock is enabled */ + if (__HAL_RCC_DMA2D_IS_CLK_ENABLED()) + { + /* Abort DMA2D transfer if any */ + if ((hdma2d->Instance->CR & DMA2D_CR_START) == DMA2D_CR_START) + { + if (HAL_DMA2D_Abort(hdma2d) != HAL_OK) + { + /* Issue when aborting DMA2D transfer */ + return HAL_ERROR; + } + } + else + { + /* Abort background CLUT loading if any */ + if ((hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START) == DMA2D_BGPFCCR_START) + { + if (HAL_DMA2D_CLUTLoading_Abort(hdma2d, 0U) != HAL_OK) + { + /* Issue when aborting background CLUT loading */ + return HAL_ERROR; + } + } + else + { + /* Abort foreground CLUT loading if any */ + if ((hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START) == DMA2D_FGPFCCR_START) + { + if (HAL_DMA2D_CLUTLoading_Abort(hdma2d, 1U) != HAL_OK) + { + /* Issue when aborting foreground CLUT loading */ + return HAL_ERROR; + } + } + } + } + } + + /* Reset DMA2D control registers*/ + hdma2d->Instance->CR = 0U; + hdma2d->Instance->IFCR = 0x3FU; + hdma2d->Instance->FGOR = 0U; + hdma2d->Instance->BGOR = 0U; + hdma2d->Instance->FGPFCCR = 0U; + hdma2d->Instance->BGPFCCR = 0U; + hdma2d->Instance->OPFCCR = 0U; + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) + + if (hdma2d->MspDeInitCallback == NULL) + { + hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit; + } + + /* DeInit the low level hardware */ + hdma2d->MspDeInitCallback(hdma2d); + +#else + /* Carry on with de-initialization of low level hardware */ + HAL_DMA2D_MspDeInit(hdma2d); +#endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */ + + /* Update error code */ + hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE; + + /* Initialize the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Initializes the DMA2D MSP. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval None + */ +__weak void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef *hdma2d) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma2d); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_DMA2D_MspInit can be implemented in the user file. + */ +} + +/** + * @brief DeInitializes the DMA2D MSP. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval None + */ +__weak void HAL_DMA2D_MspDeInit(DMA2D_HandleTypeDef *hdma2d) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma2d); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_DMA2D_MspDeInit can be implemented in the user file. + */ +} + +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User DMA2D Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hdma2d DMA2D handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_DMA2D_TRANSFERCOMPLETE_CB_ID DMA2D transfer complete Callback ID + * @arg @ref HAL_DMA2D_TRANSFERERROR_CB_ID DMA2D transfer error Callback ID + * @arg @ref HAL_DMA2D_LINEEVENT_CB_ID DMA2D line event Callback ID + * @arg @ref HAL_DMA2D_CLUTLOADINGCPLT_CB_ID DMA2D CLUT loading completion Callback ID + * @arg @ref HAL_DMA2D_MSPINIT_CB_ID DMA2D MspInit callback ID + * @arg @ref HAL_DMA2D_MSPDEINIT_CB_ID DMA2D MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @note No weak predefined callbacks are defined for HAL_DMA2D_TRANSFERCOMPLETE_CB_ID or HAL_DMA2D_TRANSFERERROR_CB_ID + * @retval status + */ +HAL_StatusTypeDef HAL_DMA2D_RegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID, + pDMA2D_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hdma2d); + + if (HAL_DMA2D_STATE_READY == hdma2d->State) + { + switch (CallbackID) + { + case HAL_DMA2D_TRANSFERCOMPLETE_CB_ID : + hdma2d->XferCpltCallback = pCallback; + break; + + case HAL_DMA2D_TRANSFERERROR_CB_ID : + hdma2d->XferErrorCallback = pCallback; + break; + + case HAL_DMA2D_LINEEVENT_CB_ID : + hdma2d->LineEventCallback = pCallback; + break; + + case HAL_DMA2D_CLUTLOADINGCPLT_CB_ID : + hdma2d->CLUTLoadingCpltCallback = pCallback; + break; + + case HAL_DMA2D_MSPINIT_CB_ID : + hdma2d->MspInitCallback = pCallback; + break; + + case HAL_DMA2D_MSPDEINIT_CB_ID : + hdma2d->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_DMA2D_STATE_RESET == hdma2d->State) + { + switch (CallbackID) + { + case HAL_DMA2D_MSPINIT_CB_ID : + hdma2d->MspInitCallback = pCallback; + break; + + case HAL_DMA2D_MSPDEINIT_CB_ID : + hdma2d->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma2d); + return status; +} + +/** + * @brief Unregister a DMA2D Callback + * DMA2D Callback is redirected to the weak (surcharged) predefined callback + * @param hdma2d DMA2D handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_DMA2D_TRANSFERCOMPLETE_CB_ID DMA2D transfer complete Callback ID + * @arg @ref HAL_DMA2D_TRANSFERERROR_CB_ID DMA2D transfer error Callback ID + * @arg @ref HAL_DMA2D_LINEEVENT_CB_ID DMA2D line event Callback ID + * @arg @ref HAL_DMA2D_CLUTLOADINGCPLT_CB_ID DMA2D CLUT loading completion Callback ID + * @arg @ref HAL_DMA2D_MSPINIT_CB_ID DMA2D MspInit callback ID + * @arg @ref HAL_DMA2D_MSPDEINIT_CB_ID DMA2D MspDeInit callback ID + * @note No weak predefined callbacks are defined for HAL_DMA2D_TRANSFERCOMPLETE_CB_ID or HAL_DMA2D_TRANSFERERROR_CB_ID + * @retval status + */ +HAL_StatusTypeDef HAL_DMA2D_UnRegisterCallback(DMA2D_HandleTypeDef *hdma2d, HAL_DMA2D_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdma2d); + + if (HAL_DMA2D_STATE_READY == hdma2d->State) + { + switch (CallbackID) + { + case HAL_DMA2D_TRANSFERCOMPLETE_CB_ID : + hdma2d->XferCpltCallback = NULL; + break; + + case HAL_DMA2D_TRANSFERERROR_CB_ID : + hdma2d->XferErrorCallback = NULL; + break; + + case HAL_DMA2D_LINEEVENT_CB_ID : + hdma2d->LineEventCallback = HAL_DMA2D_LineEventCallback; + break; + + case HAL_DMA2D_CLUTLOADINGCPLT_CB_ID : + hdma2d->CLUTLoadingCpltCallback = HAL_DMA2D_CLUTLoadingCpltCallback; + break; + + case HAL_DMA2D_MSPINIT_CB_ID : + hdma2d->MspInitCallback = HAL_DMA2D_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_DMA2D_MSPDEINIT_CB_ID : + hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_DMA2D_STATE_RESET == hdma2d->State) + { + switch (CallbackID) + { + case HAL_DMA2D_MSPINIT_CB_ID : + hdma2d->MspInitCallback = HAL_DMA2D_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_DMA2D_MSPDEINIT_CB_ID : + hdma2d->MspDeInitCallback = HAL_DMA2D_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdma2d); + return status; +} +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + +/** + * @} + */ + + +/** @defgroup DMA2D_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the pdata, destination address and data size then + start the DMA2D transfer. + (+) Configure the source for foreground and background, destination address + and data size then start a MultiBuffer DMA2D transfer. + (+) Configure the pdata, destination address and data size then + start the DMA2D transfer with interrupt. + (+) Configure the source for foreground and background, destination address + and data size then start a MultiBuffer DMA2D transfer with interrupt. + (+) Abort DMA2D transfer. + (+) Suspend DMA2D transfer. + (+) Resume DMA2D transfer. + (+) Enable CLUT transfer. + (+) Configure CLUT loading then start transfer in polling mode. + (+) Configure CLUT loading then start transfer in interrupt mode. + (+) Abort DMA2D CLUT loading. + (+) Suspend DMA2D CLUT loading. + (+) Resume DMA2D CLUT loading. + (+) Poll for transfer complete. + (+) handle DMA2D interrupt request. + (+) Transfer watermark callback. + (+) CLUT Transfer Complete callback. + + +@endverbatim + * @{ + */ + +/** + * @brief Start the DMA2D Transfer. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param pdata Configure the source memory Buffer address if + * Memory-to-Memory or Memory-to-Memory with pixel format + * conversion mode is selected, or configure + * the color value if Register-to-Memory mode is selected. + * @param DstAddress The destination memory Buffer address. + * @param Width The width of data to be transferred from source + * to destination (expressed in number of pixels per line). + * @param Height The height of data to be transferred from source to destination (expressed in number of lines). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Start(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LINE(Height)); + assert_param(IS_DMA2D_PIXEL(Width)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the source, destination address and the data size */ + DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height); + + /* Enable the Peripheral */ + __HAL_DMA2D_ENABLE(hdma2d); + + return HAL_OK; +} + +/** + * @brief Start the DMA2D Transfer with interrupt enabled. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param pdata Configure the source memory Buffer address if + * the Memory-to-Memory or Memory-to-Memory with pixel format + * conversion mode is selected, or configure + * the color value if Register-to-Memory mode is selected. + * @param DstAddress The destination memory Buffer address. + * @param Width The width of data to be transferred from source + * to destination (expressed in number of pixels per line). + * @param Height The height of data to be transferred from source to destination (expressed in number of lines). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LINE(Height)); + assert_param(IS_DMA2D_PIXEL(Width)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the source, destination address and the data size */ + DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height); + + /* Enable the transfer complete, transfer error and configuration error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC | DMA2D_IT_TE | DMA2D_IT_CE); + + /* Enable the Peripheral */ + __HAL_DMA2D_ENABLE(hdma2d); + + return HAL_OK; +} + +/** + * @brief Start the multi-source DMA2D Transfer. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param SrcAddress1 The source memory Buffer address for the foreground layer. + * @param SrcAddress2 The source memory Buffer address for the background layer. + * @param DstAddress The destination memory Buffer address. + * @param Width The width of data to be transferred from source + * to destination (expressed in number of pixels per line). + * @param Height The height of data to be transferred from source to destination (expressed in number of lines). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_BlendingStart(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, + uint32_t DstAddress, uint32_t Width, uint32_t Height) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LINE(Height)); + assert_param(IS_DMA2D_PIXEL(Width)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure DMA2D Stream source2 address */ + WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2); + + /* Configure the source, destination address and the data size */ + DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height); + + /* Enable the Peripheral */ + __HAL_DMA2D_ENABLE(hdma2d); + + return HAL_OK; +} + +/** + * @brief Start the multi-source DMA2D Transfer with interrupt enabled. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param SrcAddress1 The source memory Buffer address for the foreground layer. + * @param SrcAddress2 The source memory Buffer address for the background layer. + * @param DstAddress The destination memory Buffer address. + * @param Width The width of data to be transferred from source + * to destination (expressed in number of pixels per line). + * @param Height The height of data to be transferred from source to destination (expressed in number of lines). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_BlendingStart_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, + uint32_t DstAddress, uint32_t Width, uint32_t Height) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LINE(Height)); + assert_param(IS_DMA2D_PIXEL(Width)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure DMA2D Stream source2 address */ + WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2); + + /* Configure the source, destination address and the data size */ + DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height); + + /* Enable the transfer complete, transfer error and configuration error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC | DMA2D_IT_TE | DMA2D_IT_CE); + + /* Enable the Peripheral */ + __HAL_DMA2D_ENABLE(hdma2d); + + return HAL_OK; +} + +/** + * @brief Abort the DMA2D Transfer. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Abort(DMA2D_HandleTypeDef *hdma2d) +{ + uint32_t tickstart; + + /* Abort the DMA2D transfer */ + /* START bit is reset to make sure not to set it again, in the event the HW clears it + between the register read and the register write by the CPU (writing 0 has no + effect on START bitvalue) */ + MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_ABORT | DMA2D_CR_START, DMA2D_CR_ABORT); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if the DMA2D is effectively disabled */ + while ((hdma2d->Instance->CR & DMA2D_CR_START) != 0U) + { + if ((HAL_GetTick() - tickstart) > DMA2D_TIMEOUT_ABORT) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_TIMEOUT; + } + } + + /* Disable the Transfer Complete, Transfer Error and Configuration Error interrupts */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TC | DMA2D_IT_TE | DMA2D_IT_CE); + + /* Change the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Suspend the DMA2D Transfer. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Suspend(DMA2D_HandleTypeDef *hdma2d) +{ + uint32_t tickstart; + + /* Suspend the DMA2D transfer */ + /* START bit is reset to make sure not to set it again, in the event the HW clears it + between the register read and the register write by the CPU (writing 0 has no + effect on START bitvalue). */ + MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_SUSP | DMA2D_CR_START, DMA2D_CR_SUSP); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if the DMA2D is effectively suspended */ + while ((hdma2d->Instance->CR & (DMA2D_CR_SUSP | DMA2D_CR_START)) == DMA2D_CR_START) + { + if ((HAL_GetTick() - tickstart) > DMA2D_TIMEOUT_SUSPEND) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + } + + /* Check whether or not a transfer is actually suspended and change the DMA2D state accordingly */ + if ((hdma2d->Instance->CR & DMA2D_CR_START) != 0U) + { + hdma2d->State = HAL_DMA2D_STATE_SUSPEND; + } + else + { + /* Make sure SUSP bit is cleared since it is meaningless + when no transfer is on-going */ + CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP); + } + + return HAL_OK; +} + +/** + * @brief Resume the DMA2D Transfer. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_Resume(DMA2D_HandleTypeDef *hdma2d) +{ + /* Check the SUSP and START bits */ + if ((hdma2d->Instance->CR & (DMA2D_CR_SUSP | DMA2D_CR_START)) == (DMA2D_CR_SUSP | DMA2D_CR_START)) + { + /* Ongoing transfer is suspended: change the DMA2D state before resuming */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + } + + /* Resume the DMA2D transfer */ + /* START bit is reset to make sure not to set it again, in the event the HW clears it + between the register read and the register write by the CPU (writing 0 has no + effect on START bitvalue). */ + CLEAR_BIT(hdma2d->Instance->CR, (DMA2D_CR_SUSP | DMA2D_CR_START)); + + return HAL_OK; +} + + +/** + * @brief Enable the DMA2D CLUT Transfer. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_EnableCLUT(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Enable the background CLUT loading */ + SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START); + } + else + { + /* Enable the foreground CLUT loading */ + SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START); + } + + return HAL_OK; +} + +/** + * @brief Start DMA2D CLUT Loading. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains + * the configuration information for the color look up table. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_CLUT_CM(CLUTCfg->CLUTColorMode)); + assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg->Size)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the CLUT of the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write background CLUT memory address */ + WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg->pCLUT); + + /* Write background CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM), + ((CLUTCfg->Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos))); + + /* Enable the CLUT loading for the background */ + SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START); + } + /* Configure the CLUT of the foreground DMA2D layer */ + else + { + /* Write foreground CLUT memory address */ + WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg->pCLUT); + + /* Write foreground CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), + ((CLUTCfg->Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos))); + + /* Enable the CLUT loading for the foreground */ + SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START); + } + + return HAL_OK; +} + +/** + * @brief Start DMA2D CLUT Loading with interrupt enabled. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains + * the configuration information for the color look up table. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTStartLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef *CLUTCfg, + uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_CLUT_CM(CLUTCfg->CLUTColorMode)); + assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg->Size)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the CLUT of the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write background CLUT memory address */ + WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg->pCLUT); + + /* Write background CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM), + ((CLUTCfg->Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos))); + + /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE | DMA2D_IT_CAE); + + /* Enable the CLUT loading for the background */ + SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START); + } + /* Configure the CLUT of the foreground DMA2D layer */ + else + { + /* Write foreground CLUT memory address */ + WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg->pCLUT); + + /* Write foreground CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), + ((CLUTCfg->Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg->CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos))); + + /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE | DMA2D_IT_CAE); + + /* Enable the CLUT loading for the foreground */ + SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START); + } + + return HAL_OK; +} + +/** + * @brief Start DMA2D CLUT Loading. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains + * the configuration information for the color look up table. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @note API obsolete and maintained for compatibility with legacy. User is + * invited to resort to HAL_DMA2D_CLUTStartLoad() instead to benefit from + * code compactness, code size and improved heap usage. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTLoad(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode)); + assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the CLUT of the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write background CLUT memory address */ + WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write background CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos))); + + /* Enable the CLUT loading for the background */ + SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START); + } + /* Configure the CLUT of the foreground DMA2D layer */ + else + { + /* Write foreground CLUT memory address */ + WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write foreground CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos))); + + /* Enable the CLUT loading for the foreground */ + SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START); + } + + return HAL_OK; +} + +/** + * @brief Start DMA2D CLUT Loading with interrupt enabled. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains + * the configuration information for the color look up table. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @note API obsolete and maintained for compatibility with legacy. User is + * invited to resort to HAL_DMA2D_CLUTStartLoad_IT() instead to benefit + * from code compactness, code size and improved heap usage. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTLoad_IT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode)); + assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the CLUT of the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write background CLUT memory address */ + WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write background CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos))); + + /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE | DMA2D_IT_CAE); + + /* Enable the CLUT loading for the background */ + SET_BIT(hdma2d->Instance->BGPFCCR, DMA2D_BGPFCCR_START); + } + /* Configure the CLUT of the foreground DMA2D layer */ + else + { + /* Write foreground CLUT memory address */ + WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write foreground CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos))); + + /* Enable the CLUT Transfer Complete, transfer Error, configuration Error and CLUT Access Error interrupts */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE | DMA2D_IT_CAE); + + /* Enable the CLUT loading for the foreground */ + SET_BIT(hdma2d->Instance->FGPFCCR, DMA2D_FGPFCCR_START); + } + + return HAL_OK; +} + +/** + * @brief Abort the DMA2D CLUT loading. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Abort(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) +{ + uint32_t tickstart; + const __IO uint32_t *reg = &(hdma2d->Instance->BGPFCCR); /* by default, point at background register */ + + /* Abort the CLUT loading */ + SET_BIT(hdma2d->Instance->CR, DMA2D_CR_ABORT); + + /* If foreground CLUT loading is considered, update local variables */ + if (LayerIdx == DMA2D_FOREGROUND_LAYER) + { + reg = &(hdma2d->Instance->FGPFCCR); + } + + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if the CLUT loading is aborted */ + while ((*reg & DMA2D_BGPFCCR_START) != 0U) + { + if ((HAL_GetTick() - tickstart) > DMA2D_TIMEOUT_ABORT) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_TIMEOUT; + } + } + + /* Disable the CLUT Transfer Complete, Transfer Error, Configuration Error and CLUT Access Error interrupts */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CTC | DMA2D_IT_TE | DMA2D_IT_CE | DMA2D_IT_CAE); + + /* Change the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Suspend the DMA2D CLUT loading. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Suspend(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) +{ + uint32_t tickstart; + uint32_t loadsuspended; + const __IO uint32_t *reg = &(hdma2d->Instance->BGPFCCR); /* by default, point at background register */ + + /* Suspend the CLUT loading */ + SET_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP); + + /* If foreground CLUT loading is considered, update local variables */ + if (LayerIdx == DMA2D_FOREGROUND_LAYER) + { + reg = &(hdma2d->Instance->FGPFCCR); + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check if the CLUT loading is suspended */ + /* 1st condition: Suspend Check */ + loadsuspended = ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP) ? 1UL : 0UL; + /* 2nd condition: Not Start Check */ + loadsuspended |= ((*reg & DMA2D_BGPFCCR_START) != DMA2D_BGPFCCR_START) ? 1UL : 0UL; + while (loadsuspended == 0UL) + { + if ((HAL_GetTick() - tickstart) > DMA2D_TIMEOUT_SUSPEND) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + return HAL_TIMEOUT; + } + /* 1st condition: Suspend Check */ + loadsuspended = ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP) ? 1UL : 0UL; + /* 2nd condition: Not Start Check */ + loadsuspended |= ((*reg & DMA2D_BGPFCCR_START) != DMA2D_BGPFCCR_START) ? 1UL : 0UL; + } + + /* Check whether or not a transfer is actually suspended and change the DMA2D state accordingly */ + if ((*reg & DMA2D_BGPFCCR_START) != 0U) + { + hdma2d->State = HAL_DMA2D_STATE_SUSPEND; + } + else + { + /* Make sure SUSP bit is cleared since it is meaningless + when no transfer is on-going */ + CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP); + } + + return HAL_OK; +} + +/** + * @brief Resume the DMA2D CLUT loading. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_CLUTLoading_Resume(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) +{ + /* Check the SUSP and START bits for background or foreground CLUT loading */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Background CLUT loading suspension check */ + if ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP) + { + if ((hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START) == DMA2D_BGPFCCR_START) + { + /* Ongoing CLUT loading is suspended: change the DMA2D state before resuming */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + } + } + } + else + { + /* Foreground CLUT loading suspension check */ + if ((hdma2d->Instance->CR & DMA2D_CR_SUSP) == DMA2D_CR_SUSP) + { + if ((hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START) == DMA2D_FGPFCCR_START) + { + /* Ongoing CLUT loading is suspended: change the DMA2D state before resuming */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + } + } + } + + /* Resume the CLUT loading */ + CLEAR_BIT(hdma2d->Instance->CR, DMA2D_CR_SUSP); + + return HAL_OK; +} + + +/** + + * @brief Polling for transfer complete or CLUT loading. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_PollForTransfer(DMA2D_HandleTypeDef *hdma2d, uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t layer_start; + __IO uint32_t isrflags = 0x0U; + + /* Polling for DMA2D transfer */ + if ((hdma2d->Instance->CR & DMA2D_CR_START) != 0U) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + while (__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_TC) == 0U) + { + isrflags = READ_REG(hdma2d->Instance->ISR); + if ((isrflags & (DMA2D_FLAG_CE | DMA2D_FLAG_TE)) != 0U) + { + if ((isrflags & DMA2D_FLAG_CE) != 0U) + { + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE; + } + if ((isrflags & DMA2D_FLAG_TE) != 0U) + { + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE; + } + /* Clear the transfer and configuration error flags */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CE | DMA2D_FLAG_TE); + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_ERROR; + } + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_TIMEOUT; + } + } + } + } + /* Polling for CLUT loading (foreground or background) */ + layer_start = hdma2d->Instance->FGPFCCR & DMA2D_FGPFCCR_START; + layer_start |= hdma2d->Instance->BGPFCCR & DMA2D_BGPFCCR_START; + if (layer_start != 0U) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + while (__HAL_DMA2D_GET_FLAG(hdma2d, DMA2D_FLAG_CTC) == 0U) + { + isrflags = READ_REG(hdma2d->Instance->ISR); + if ((isrflags & (DMA2D_FLAG_CAE | DMA2D_FLAG_CE | DMA2D_FLAG_TE)) != 0U) + { + if ((isrflags & DMA2D_FLAG_CAE) != 0U) + { + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CAE; + } + if ((isrflags & DMA2D_FLAG_CE) != 0U) + { + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE; + } + if ((isrflags & DMA2D_FLAG_TE) != 0U) + { + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE; + } + /* Clear the CLUT Access Error, Configuration Error and Transfer Error flags */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CAE | DMA2D_FLAG_CE | DMA2D_FLAG_TE); + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_ERROR; + } + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TIMEOUT; + + /* Change the DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_TIMEOUT; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_TIMEOUT; + } + } + } + } + + /* Clear the transfer complete and CLUT loading flags */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TC | DMA2D_FLAG_CTC); + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} +/** + * @brief Handle DMA2D interrupt request. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL status + */ +void HAL_DMA2D_IRQHandler(DMA2D_HandleTypeDef *hdma2d) +{ + uint32_t isrflags = READ_REG(hdma2d->Instance->ISR); + uint32_t crflags = READ_REG(hdma2d->Instance->CR); + + /* Transfer Error Interrupt management ***************************************/ + if ((isrflags & DMA2D_FLAG_TE) != 0U) + { + if ((crflags & DMA2D_IT_TE) != 0U) + { + /* Disable the transfer Error interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TE); + + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_TE; + + /* Clear the transfer error flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TE); + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + if (hdma2d->XferErrorCallback != NULL) + { + /* Transfer error Callback */ + hdma2d->XferErrorCallback(hdma2d); + } + } + } + /* Configuration Error Interrupt management **********************************/ + if ((isrflags & DMA2D_FLAG_CE) != 0U) + { + if ((crflags & DMA2D_IT_CE) != 0U) + { + /* Disable the Configuration Error interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CE); + + /* Clear the Configuration error flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CE); + + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CE; + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + if (hdma2d->XferErrorCallback != NULL) + { + /* Transfer error Callback */ + hdma2d->XferErrorCallback(hdma2d); + } + } + } + /* CLUT access Error Interrupt management ***********************************/ + if ((isrflags & DMA2D_FLAG_CAE) != 0U) + { + if ((crflags & DMA2D_IT_CAE) != 0U) + { + /* Disable the CLUT access error interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CAE); + + /* Clear the CLUT access error flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CAE); + + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_CAE; + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + if (hdma2d->XferErrorCallback != NULL) + { + /* Transfer error Callback */ + hdma2d->XferErrorCallback(hdma2d); + } + } + } + /* Transfer watermark Interrupt management **********************************/ + if ((isrflags & DMA2D_FLAG_TW) != 0U) + { + if ((crflags & DMA2D_IT_TW) != 0U) + { + /* Disable the transfer watermark interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TW); + + /* Clear the transfer watermark flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TW); + + /* Transfer watermark Callback */ +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) + hdma2d->LineEventCallback(hdma2d); +#else + HAL_DMA2D_LineEventCallback(hdma2d); +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + + } + } + /* Transfer Complete Interrupt management ************************************/ + if ((isrflags & DMA2D_FLAG_TC) != 0U) + { + if ((crflags & DMA2D_IT_TC) != 0U) + { + /* Disable the transfer complete interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_TC); + + /* Clear the transfer complete flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_TC); + + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_NONE; + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + if (hdma2d->XferCpltCallback != NULL) + { + /* Transfer complete Callback */ + hdma2d->XferCpltCallback(hdma2d); + } + } + } + /* CLUT Transfer Complete Interrupt management ******************************/ + if ((isrflags & DMA2D_FLAG_CTC) != 0U) + { + if ((crflags & DMA2D_IT_CTC) != 0U) + { + /* Disable the CLUT transfer complete interrupt */ + __HAL_DMA2D_DISABLE_IT(hdma2d, DMA2D_IT_CTC); + + /* Clear the CLUT transfer complete flag */ + __HAL_DMA2D_CLEAR_FLAG(hdma2d, DMA2D_FLAG_CTC); + + /* Update error code */ + hdma2d->ErrorCode |= HAL_DMA2D_ERROR_NONE; + + /* Change DMA2D state */ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + /* CLUT Transfer complete Callback */ +#if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) + hdma2d->CLUTLoadingCpltCallback(hdma2d); +#else + HAL_DMA2D_CLUTLoadingCpltCallback(hdma2d); +#endif /* USE_HAL_DMA2D_REGISTER_CALLBACKS */ + } + } + +} + +/** + * @brief Transfer watermark callback. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval None + */ +__weak void HAL_DMA2D_LineEventCallback(DMA2D_HandleTypeDef *hdma2d) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma2d); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_DMA2D_LineEventCallback can be implemented in the user file. + */ +} + +/** + * @brief CLUT Transfer Complete callback. + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval None + */ +__weak void HAL_DMA2D_CLUTLoadingCpltCallback(DMA2D_HandleTypeDef *hdma2d) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma2d); + + /* NOTE : This function should not be modified; when the callback is needed, + the HAL_DMA2D_CLUTLoadingCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup DMA2D_Exported_Functions_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the DMA2D foreground or background layer parameters. + (+) Configure the DMA2D CLUT transfer. + (+) Configure the line watermark + (+) Configure the dead time value. + (+) Enable or disable the dead time value functionality. + + +@endverbatim + * @{ + */ + +/** + * @brief Configure the DMA2D Layer according to the specified + * parameters in the DMA2D_HandleTypeDef. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) +{ + DMA2D_LayerCfgTypeDef *pLayerCfg; + uint32_t regMask; + uint32_t regValue; + + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_OFFSET(hdma2d->LayerCfg[LayerIdx].InputOffset)); + if (hdma2d->Init.Mode != DMA2D_R2M) + { + assert_param(IS_DMA2D_INPUT_COLOR_MODE(hdma2d->LayerCfg[LayerIdx].InputColorMode)); + if (hdma2d->Init.Mode != DMA2D_M2M) + { + assert_param(IS_DMA2D_ALPHA_MODE(hdma2d->LayerCfg[LayerIdx].AlphaMode)); + } + } + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + pLayerCfg = &hdma2d->LayerCfg[LayerIdx]; + + /* Prepare the value to be written to the BGPFCCR or FGPFCCR register */ + regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_BGPFCCR_AM_Pos); + regMask = DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA; + + + if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) + { + regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA); + } + else + { + regValue |= (pLayerCfg->InputAlpha << DMA2D_BGPFCCR_ALPHA_Pos); + } + + /* Configure the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write DMA2D BGPFCCR register */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue); + + /* DMA2D BGOR register configuration -------------------------------------*/ + WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset); + + /* DMA2D BGCOLR register configuration -------------------------------------*/ + if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) + { + WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha & (DMA2D_BGCOLR_BLUE | DMA2D_BGCOLR_GREEN | \ + DMA2D_BGCOLR_RED)); + } + } + /* Configure the foreground DMA2D layer */ + else + { + + + /* Write DMA2D FGPFCCR register */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue); + + /* DMA2D FGOR register configuration -------------------------------------*/ + WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset); + + /* DMA2D FGCOLR register configuration -------------------------------------*/ + if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) + { + WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha & (DMA2D_FGCOLR_BLUE | DMA2D_FGCOLR_GREEN | \ + DMA2D_FGCOLR_RED)); + } + } + /* Initialize the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Configure the DMA2D CLUT Transfer. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param CLUTCfg Pointer to a DMA2D_CLUTCfgTypeDef structure that contains + * the configuration information for the color look up table. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * DMA2D_BACKGROUND_LAYER(0) / DMA2D_FOREGROUND_LAYER(1) + * @note API obsolete and maintained for compatibility with legacy. User is invited + * to resort to HAL_DMA2D_CLUTStartLoad() instead to benefit from code compactness, + * code size and improved heap usage. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_ConfigCLUT(DMA2D_HandleTypeDef *hdma2d, DMA2D_CLUTCfgTypeDef CLUTCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_DMA2D_LAYER(LayerIdx)); + assert_param(IS_DMA2D_CLUT_CM(CLUTCfg.CLUTColorMode)); + assert_param(IS_DMA2D_CLUT_SIZE(CLUTCfg.Size)); + + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Configure the CLUT of the background DMA2D layer */ + if (LayerIdx == DMA2D_BACKGROUND_LAYER) + { + /* Write background CLUT memory address */ + WRITE_REG(hdma2d->Instance->BGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write background CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->BGPFCCR, (DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_BGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_BGPFCCR_CCM_Pos))); + } + /* Configure the CLUT of the foreground DMA2D layer */ + else + { + /* Write foreground CLUT memory address */ + WRITE_REG(hdma2d->Instance->FGCMAR, (uint32_t)CLUTCfg.pCLUT); + + /* Write foreground CLUT size and CLUT color mode */ + MODIFY_REG(hdma2d->Instance->FGPFCCR, (DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM), + ((CLUTCfg.Size << DMA2D_FGPFCCR_CS_Pos) | (CLUTCfg.CLUTColorMode << DMA2D_FGPFCCR_CCM_Pos))); + } + + /* Set the DMA2D state to Ready*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + + +/** + * @brief Configure the line watermark. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @param Line Line Watermark configuration (maximum 16-bit long value expected). + * @note HAL_DMA2D_ProgramLineEvent() API enables the transfer watermark interrupt. + * @note The transfer watermark interrupt is disabled once it has occurred. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_DMA2D_ProgramLineEvent(DMA2D_HandleTypeDef *hdma2d, uint32_t Line) +{ + /* Check the parameters */ + if (Line > DMA2D_LWR_LW) + { + return HAL_ERROR; + } + else + { + /* Process locked */ + __HAL_LOCK(hdma2d); + + /* Change DMA2D peripheral state */ + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Sets the Line watermark configuration */ + WRITE_REG(hdma2d->Instance->LWR, Line); + + /* Enable the Line interrupt */ + __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TW); + + /* Initialize the DMA2D state*/ + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; + } +} + +/** + * @brief Enable DMA2D dead time feature. + * @param hdma2d DMA2D handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_EnableDeadTime(DMA2D_HandleTypeDef *hdma2d) +{ + /* Process Locked */ + __HAL_LOCK(hdma2d); + + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Set DMA2D_AMTCR EN bit */ + SET_BIT(hdma2d->Instance->AMTCR, DMA2D_AMTCR_EN); + + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Disable DMA2D dead time feature. + * @param hdma2d DMA2D handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_DisableDeadTime(DMA2D_HandleTypeDef *hdma2d) +{ + /* Process Locked */ + __HAL_LOCK(hdma2d); + + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Clear DMA2D_AMTCR EN bit */ + CLEAR_BIT(hdma2d->Instance->AMTCR, DMA2D_AMTCR_EN); + + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @brief Configure dead time. + * @note The dead time value represents the guaranteed minimum number of cycles between + * two consecutive transactions on the AHB bus. + * @param hdma2d DMA2D handle. + * @param DeadTime dead time value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DMA2D_ConfigDeadTime(DMA2D_HandleTypeDef *hdma2d, uint8_t DeadTime) +{ + /* Process Locked */ + __HAL_LOCK(hdma2d); + + hdma2d->State = HAL_DMA2D_STATE_BUSY; + + /* Set DMA2D_AMTCR DT field */ + MODIFY_REG(hdma2d->Instance->AMTCR, DMA2D_AMTCR_DT, (((uint32_t) DeadTime) << DMA2D_AMTCR_DT_Pos)); + + hdma2d->State = HAL_DMA2D_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hdma2d); + + return HAL_OK; +} + +/** + * @} + */ + + +/** @defgroup DMA2D_Exported_Functions_Group4 Peripheral State and Error functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to: + (+) Get the DMA2D state + (+) Get the DMA2D error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the DMA2D state + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the DMA2D. + * @retval HAL state + */ +HAL_DMA2D_StateTypeDef HAL_DMA2D_GetState(DMA2D_HandleTypeDef *hdma2d) +{ + return hdma2d->State; +} + +/** + * @brief Return the DMA2D error code + * @param hdma2d pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for DMA2D. + * @retval DMA2D Error Code + */ +uint32_t HAL_DMA2D_GetError(DMA2D_HandleTypeDef *hdma2d) +{ + return hdma2d->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + + +/** @defgroup DMA2D_Private_Functions DMA2D Private Functions + * @{ + */ + +/** + * @brief Set the DMA2D transfer parameters. + * @param hdma2d Pointer to a DMA2D_HandleTypeDef structure that contains + * the configuration information for the specified DMA2D. + * @param pdata The source memory Buffer address + * @param DstAddress The destination memory Buffer address + * @param Width The width of data to be transferred from source to destination. + * @param Height The height of data to be transferred from source to destination. + * @retval HAL status + */ +static void DMA2D_SetConfig(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, + uint32_t Height) +{ + uint32_t tmp; + uint32_t tmp1; + uint32_t tmp2; + uint32_t tmp3; + uint32_t tmp4; + + /* Configure DMA2D data size */ + MODIFY_REG(hdma2d->Instance->NLR, (DMA2D_NLR_NL | DMA2D_NLR_PL), (Height | (Width << DMA2D_NLR_PL_Pos))); + + /* Configure DMA2D destination address */ + WRITE_REG(hdma2d->Instance->OMAR, DstAddress); + + /* Register to memory DMA2D mode selected */ + if (hdma2d->Init.Mode == DMA2D_R2M) + { + tmp1 = pdata & DMA2D_OCOLR_ALPHA_1; + tmp2 = pdata & DMA2D_OCOLR_RED_1; + tmp3 = pdata & DMA2D_OCOLR_GREEN_1; + tmp4 = pdata & DMA2D_OCOLR_BLUE_1; + + /* Prepare the value to be written to the OCOLR register according to the color mode */ + if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_ARGB8888) + { + tmp = (tmp3 | tmp2 | tmp1 | tmp4); + } + else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_RGB888) + { + tmp = (tmp3 | tmp2 | tmp4); + } + else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_RGB565) + { + tmp2 = (tmp2 >> 19U); + tmp3 = (tmp3 >> 10U); + tmp4 = (tmp4 >> 3U); + tmp = ((tmp3 << 5U) | (tmp2 << 11U) | tmp4); + } + else if (hdma2d->Init.ColorMode == DMA2D_OUTPUT_ARGB1555) + { + tmp1 = (tmp1 >> 31U); + tmp2 = (tmp2 >> 19U); + tmp3 = (tmp3 >> 11U); + tmp4 = (tmp4 >> 3U); + tmp = ((tmp3 << 5U) | (tmp2 << 10U) | (tmp1 << 15U) | tmp4); + } + else /* Dhdma2d->Init.ColorMode = DMA2D_OUTPUT_ARGB4444 */ + { + tmp1 = (tmp1 >> 28U); + tmp2 = (tmp2 >> 20U); + tmp3 = (tmp3 >> 12U); + tmp4 = (tmp4 >> 4U); + tmp = ((tmp3 << 4U) | (tmp2 << 8U) | (tmp1 << 12U) | tmp4); + } + /* Write to DMA2D OCOLR register */ + WRITE_REG(hdma2d->Instance->OCOLR, tmp); + } + else /* M2M, M2M_PFC or M2M_Blending DMA2D Mode */ + { + /* Configure DMA2D source address */ + WRITE_REG(hdma2d->Instance->FGMAR, pdata); + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* DMA2D */ +#endif /* HAL_DMA2D_MODULE_ENABLED */ diff --git a/libs/hal/stm32f4xx_hal_dma_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_dma_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c new file mode 100644 index 0000000..2ae7faa --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dsi.c @@ -0,0 +1,3117 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_dsi.c + * @author MCD Application Team + * @brief DSI HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the DSI peripheral: + * + 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 DSI HAL driver can be used as follows: + + (#) Declare a DSI_HandleTypeDef handle structure, for example: DSI_HandleTypeDef hdsi; + + (#) Initialize the DSI low level resources by implementing the HAL_DSI_MspInit() API: + (##) Enable the DSI interface clock + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the DSI interrupt priority + (+++) Enable the NVIC DSI IRQ Channel + + (#) Initialize the DSI Host peripheral, the required PLL parameters, number of lances and + TX Escape clock divider by calling the HAL_DSI_Init() API which calls HAL_DSI_MspInit(). + + *** Configuration *** + ========================= + [..] + (#) Use HAL_DSI_ConfigAdaptedCommandMode() function to configure the DSI host in adapted + command mode. + + (#) When operating in video mode , use HAL_DSI_ConfigVideoMode() to configure the DSI host. + + (#) Function HAL_DSI_ConfigCommand() is used to configure the DSI commands behavior in low power mode. + + (#) To configure the DSI PHY timings parameters, use function HAL_DSI_ConfigPhyTimer(). + + (#) The DSI Host can be started/stopped using respectively functions HAL_DSI_Start() and HAL_DSI_Stop(). + Functions HAL_DSI_ShortWrite(), HAL_DSI_LongWrite() and HAL_DSI_Read() allows respectively + to write DSI short packets, long packets and to read DSI packets. + + (#) The DSI Host Offers two Low power modes : + (++) Low Power Mode on data lanes only: Only DSI data lanes are shut down. + It is possible to enter/exit from this mode using respectively functions HAL_DSI_EnterULPMData() + and HAL_DSI_ExitULPMData() + + (++) Low Power Mode on data and clock lanes : All DSI lanes are shut down including data and clock lanes. + It is possible to enter/exit from this mode using respectively functions HAL_DSI_EnterULPM() + and HAL_DSI_ExitULPM() + + (#) To control DSI state you can use the following function: HAL_DSI_GetState() + + *** Error management *** + ======================== + [..] + (#) User can select the DSI errors to be reported/monitored using function HAL_DSI_ConfigErrorMonitor() + When an error occurs, the callback HAL_DSI_ErrorCallback() is asserted and then user can retrieve + the error code by calling function HAL_DSI_GetError() + + *** DSI HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in DSI HAL driver. + + (+) __HAL_DSI_ENABLE: Enable the DSI Host. + (+) __HAL_DSI_DISABLE: Disable the DSI Host. + (+) __HAL_DSI_WRAPPER_ENABLE: Enables the DSI wrapper. + (+) __HAL_DSI_WRAPPER_DISABLE: Disable the DSI wrapper. + (+) __HAL_DSI_PLL_ENABLE: Enables the DSI PLL. + (+) __HAL_DSI_PLL_DISABLE: Disables the DSI PLL. + (+) __HAL_DSI_REG_ENABLE: Enables the DSI regulator. + (+) __HAL_DSI_REG_DISABLE: Disables the DSI regulator. + (+) __HAL_DSI_GET_FLAG: Get the DSI pending flags. + (+) __HAL_DSI_CLEAR_FLAG: Clears the DSI pending flags. + (+) __HAL_DSI_ENABLE_IT: Enables the specified DSI interrupts. + (+) __HAL_DSI_DISABLE_IT: Disables the specified DSI interrupts. + (+) __HAL_DSI_GET_IT_SOURCE: Checks whether the specified DSI interrupt source is enabled or not. + + [..] + (@) You can refer to the DSI HAL driver header file for more useful macros + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_DSI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_DSI_RegisterCallback() to register a callback. + + [..] + Function HAL_DSI_RegisterCallback() allows to register following callbacks: + (+) TearingEffectCallback : DSI Tearing Effect Callback. + (+) EndOfRefreshCallback : DSI End Of Refresh Callback. + (+) ErrorCallback : DSI Error Callback + (+) MspInitCallback : DSI MspInit. + (+) MspDeInitCallback : DSI MspDeInit. + [..] + This function takes as parameters the HAL peripheral handle, the callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_DSI_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_DSI_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the callback ID. + [..] + This function allows to reset following callbacks: + (+) TearingEffectCallback : DSI Tearing Effect Callback. + (+) EndOfRefreshCallback : DSI End Of Refresh Callback. + (+) ErrorCallback : DSI Error Callback + (+) MspInitCallback : DSI MspInit. + (+) MspDeInitCallback : DSI MspDeInit. + + [..] + By default, after the HAL_DSI_Init and when the state is HAL_DSI_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_DSI_TearingEffectCallback(), HAL_DSI_EndOfRefreshCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_DSI_Init() + and HAL_DSI_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_DSI_Init() and HAL_DSI_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_DSI_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_DSI_STATE_READY or HAL_DSI_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_DSI_RegisterCallback() before calling HAL_DSI_DeInit() + or HAL_DSI_Init() function. + + [..] + When The compilation define USE_HAL_DSI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_DSI_MODULE_ENABLED + +#if defined(DSI) + +/** @addtogroup DSI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @addtogroup DSI_Private_Constants + * @{ + */ +#define DSI_TIMEOUT_VALUE ((uint32_t)1000U) /* 1s */ + +#define DSI_ERROR_ACK_MASK (DSI_ISR0_AE0 | DSI_ISR0_AE1 | DSI_ISR0_AE2 | DSI_ISR0_AE3 | \ + DSI_ISR0_AE4 | DSI_ISR0_AE5 | DSI_ISR0_AE6 | DSI_ISR0_AE7 | \ + DSI_ISR0_AE8 | DSI_ISR0_AE9 | DSI_ISR0_AE10 | DSI_ISR0_AE11 | \ + DSI_ISR0_AE12 | DSI_ISR0_AE13 | DSI_ISR0_AE14 | DSI_ISR0_AE15) +#define DSI_ERROR_PHY_MASK (DSI_ISR0_PE0 | DSI_ISR0_PE1 | DSI_ISR0_PE2 | DSI_ISR0_PE3 | DSI_ISR0_PE4) +#define DSI_ERROR_TX_MASK DSI_ISR1_TOHSTX +#define DSI_ERROR_RX_MASK DSI_ISR1_TOLPRX +#define DSI_ERROR_ECC_MASK (DSI_ISR1_ECCSE | DSI_ISR1_ECCME) +#define DSI_ERROR_CRC_MASK DSI_ISR1_CRCE +#define DSI_ERROR_PSE_MASK DSI_ISR1_PSE +#define DSI_ERROR_EOT_MASK DSI_ISR1_EOTPE +#define DSI_ERROR_OVF_MASK DSI_ISR1_LPWRE +#define DSI_ERROR_GEN_MASK (DSI_ISR1_GCWRE | DSI_ISR1_GPWRE | DSI_ISR1_GPTXE | DSI_ISR1_GPRDE | DSI_ISR1_GPRXE) +/** + * @} + */ + +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void DSI_ConfigPacketHeader(DSI_TypeDef *DSIx, uint32_t ChannelID, uint32_t DataType, uint32_t Data0, + uint32_t Data1); + +static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t Param1, + uint32_t Param2); +/* Private functions ---------------------------------------------------------*/ +/** @defgroup DSI_Private_Functions DSI Private Functions + * @{ + */ +/** + * @brief Generic DSI packet header configuration + * @param DSIx Pointer to DSI register base + * @param ChannelID Virtual channel ID of the header packet + * @param DataType Packet data type of the header packet + * This parameter can be any value of : + * @arg DSI_SHORT_WRITE_PKT_Data_Type + * @arg DSI_LONG_WRITE_PKT_Data_Type + * @arg DSI_SHORT_READ_PKT_Data_Type + * @arg DSI_MAX_RETURN_PKT_SIZE + * @param Data0 Word count LSB + * @param Data1 Word count MSB + * @retval None + */ +static void DSI_ConfigPacketHeader(DSI_TypeDef *DSIx, + uint32_t ChannelID, + uint32_t DataType, + uint32_t Data0, + uint32_t Data1) +{ + /* Update the DSI packet header with new information */ + DSIx->GHCR = (DataType | (ChannelID << 6U) | (Data0 << 8U) | (Data1 << 16U)); +} + +/** + * @brief write short DCS or short Generic command + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ChannelID Virtual channel ID. + * @param Mode DSI short packet data type. + * This parameter can be any value of @arg DSI_SHORT_WRITE_PKT_Data_Type. + * @param Param1 DSC command or first generic parameter. + * This parameter can be any value of @arg DSI_DCS_Command or a + * generic command code. + * @param Param2 DSC parameter or second generic parameter. + * @retval HAL status + */ +static HAL_StatusTypeDef DSI_ShortWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t Param1, + uint32_t Param2) +{ + uint32_t tickstart; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for Command FIFO Empty */ + while ((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Configure the packet to send a short DCS command with 0 or 1 parameter */ + /* Update the DSI packet header with new information */ + hdsi->Instance->GHCR = (Mode | (ChannelID << 6U) | (Param1 << 8U) | (Param2 << 16U)); + + return HAL_OK; +} + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DSI_Exported_Functions + * @{ + */ + +/** @defgroup DSI_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the DSI + (+) De-initialize the DSI + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the DSI according to the specified + * parameters in the DSI_InitTypeDef and create the associated handle. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param PLLInit pointer to a DSI_PLLInitTypeDef structure that contains + * the PLL Clock structure definition for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Init(DSI_HandleTypeDef *hdsi, DSI_PLLInitTypeDef *PLLInit) +{ + uint32_t tickstart; + uint32_t unitIntervalx4; + uint32_t tempIDF; + + /* Check the DSI handle allocation */ + if (hdsi == NULL) + { + return HAL_ERROR; + } + + /* Check function parameters */ + assert_param(IS_DSI_PLL_NDIV(PLLInit->PLLNDIV)); + assert_param(IS_DSI_PLL_IDF(PLLInit->PLLIDF)); + assert_param(IS_DSI_PLL_ODF(PLLInit->PLLODF)); + assert_param(IS_DSI_AUTO_CLKLANE_CONTROL(hdsi->Init.AutomaticClockLaneControl)); + assert_param(IS_DSI_NUMBER_OF_LANES(hdsi->Init.NumberOfLanes)); + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + if (hdsi->State == HAL_DSI_STATE_RESET) + { + /* Reset the DSI callback to the legacy weak callbacks */ + hdsi->TearingEffectCallback = HAL_DSI_TearingEffectCallback; /* Legacy weak TearingEffectCallback */ + hdsi->EndOfRefreshCallback = HAL_DSI_EndOfRefreshCallback; /* Legacy weak EndOfRefreshCallback */ + hdsi->ErrorCallback = HAL_DSI_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hdsi->MspInitCallback == NULL) + { + hdsi->MspInitCallback = HAL_DSI_MspInit; + } + /* Initialize the low level hardware */ + hdsi->MspInitCallback(hdsi); + } +#else + if (hdsi->State == HAL_DSI_STATE_RESET) + { + /* Initialize the low level hardware */ + HAL_DSI_MspInit(hdsi); + } +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + + /* Change DSI peripheral state */ + hdsi->State = HAL_DSI_STATE_BUSY; + + /**************** Turn on the regulator and enable the DSI PLL ****************/ + + /* Enable the regulator */ + __HAL_DSI_REG_ENABLE(hdsi); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until the regulator is ready */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_RRS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /* Set the PLL division factors */ + hdsi->Instance->WRPCR &= ~(DSI_WRPCR_PLL_NDIV | DSI_WRPCR_PLL_IDF | DSI_WRPCR_PLL_ODF); + hdsi->Instance->WRPCR |= (((PLLInit->PLLNDIV) << DSI_WRPCR_PLL_NDIV_Pos) | \ + ((PLLInit->PLLIDF) << DSI_WRPCR_PLL_IDF_Pos) | \ + ((PLLInit->PLLODF) << DSI_WRPCR_PLL_ODF_Pos)); + + /* Enable the DSI PLL */ + __HAL_DSI_PLL_ENABLE(hdsi); + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + /*************************** Set the PHY parameters ***************************/ + + /* D-PHY clock and digital enable*/ + hdsi->Instance->PCTLR |= (DSI_PCTLR_CKE | DSI_PCTLR_DEN); + + /* Clock lane configuration */ + hdsi->Instance->CLCR &= ~(DSI_CLCR_DPCC | DSI_CLCR_ACR); + hdsi->Instance->CLCR |= (DSI_CLCR_DPCC | hdsi->Init.AutomaticClockLaneControl); + + /* Configure the number of active data lanes */ + hdsi->Instance->PCONFR &= ~DSI_PCONFR_NL; + hdsi->Instance->PCONFR |= hdsi->Init.NumberOfLanes; + + /************************ Set the DSI clock parameters ************************/ + + /* Set the TX escape clock division factor */ + hdsi->Instance->CCR &= ~DSI_CCR_TXECKDIV; + hdsi->Instance->CCR |= hdsi->Init.TXEscapeCkdiv; + + /* Calculate the bit period in high-speed mode in unit of 0.25 ns (UIX4) */ + /* The equation is : UIX4 = IntegerPart( (1000/F_PHY_Mhz) * 4 ) */ + /* Where : F_PHY_Mhz = (NDIV * HSE_Mhz) / (IDF * ODF) */ + tempIDF = (PLLInit->PLLIDF > 0U) ? PLLInit->PLLIDF : 1U; + unitIntervalx4 = (4000000U * tempIDF * ((1UL << (0x3U & PLLInit->PLLODF)))) / ((HSE_VALUE / 1000U) * PLLInit->PLLNDIV); + + /* Set the bit period in high-speed mode */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_UIX4; + hdsi->Instance->WPCR[0U] |= unitIntervalx4; + + /****************************** Error management *****************************/ + + /* Disable all error interrupts and reset the Error Mask */ + hdsi->Instance->IER[0U] = 0U; + hdsi->Instance->IER[1U] = 0U; + hdsi->ErrorMsk = 0U; + + /* Initialize the error code */ + hdsi->ErrorCode = HAL_DSI_ERROR_NONE; + + /* Initialize the DSI state*/ + hdsi->State = HAL_DSI_STATE_READY; + + return HAL_OK; +} + +/** + * @brief De-initializes the DSI peripheral registers to their default reset + * values. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_DeInit(DSI_HandleTypeDef *hdsi) +{ + /* Check the DSI handle allocation */ + if (hdsi == NULL) + { + return HAL_ERROR; + } + + /* Change DSI peripheral state */ + hdsi->State = HAL_DSI_STATE_BUSY; + + /* Disable the DSI wrapper */ + __HAL_DSI_WRAPPER_DISABLE(hdsi); + + /* Disable the DSI host */ + __HAL_DSI_DISABLE(hdsi); + + /* D-PHY clock and digital disable */ + hdsi->Instance->PCTLR &= ~(DSI_PCTLR_CKE | DSI_PCTLR_DEN); + + /* Turn off the DSI PLL */ + __HAL_DSI_PLL_DISABLE(hdsi); + + /* Disable the regulator */ + __HAL_DSI_REG_DISABLE(hdsi); + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + if (hdsi->MspDeInitCallback == NULL) + { + hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; + } + /* DeInit the low level hardware */ + hdsi->MspDeInitCallback(hdsi); +#else + /* DeInit the low level hardware */ + HAL_DSI_MspDeInit(hdsi); +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + + /* Initialize the error code */ + hdsi->ErrorCode = HAL_DSI_ERROR_NONE; + + /* Initialize the DSI state*/ + hdsi->State = HAL_DSI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Enable the error monitor flags + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ActiveErrors indicates which error interrupts will be enabled. + * This parameter can be any combination of @arg DSI_Error_Data_Type. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigErrorMonitor(DSI_HandleTypeDef *hdsi, uint32_t ActiveErrors) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + hdsi->Instance->IER[0U] = 0U; + hdsi->Instance->IER[1U] = 0U; + + /* Store active errors to the handle */ + hdsi->ErrorMsk = ActiveErrors; + + if ((ActiveErrors & HAL_DSI_ERROR_ACK) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[0U] |= DSI_ERROR_ACK_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_PHY) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[0U] |= DSI_ERROR_PHY_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_TX) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_TX_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_RX) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_RX_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_ECC) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_ECC_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_CRC) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_CRC_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_PSE) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_PSE_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_EOT) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_EOT_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_OVF) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_OVF_MASK; + } + + if ((ActiveErrors & HAL_DSI_ERROR_GEN) != 0U) + { + /* Enable the interrupt generation on selected errors */ + hdsi->Instance->IER[1U] |= DSI_ERROR_GEN_MASK; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Initializes the DSI MSP. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval None + */ +__weak void HAL_DSI_MspInit(DSI_HandleTypeDef *hdsi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdsi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DSI_MspInit could be implemented in the user file + */ +} + +/** + * @brief De-initializes the DSI MSP. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval None + */ +__weak void HAL_DSI_MspDeInit(DSI_HandleTypeDef *hdsi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdsi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DSI_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User DSI Callback + * To be used instead of the weak predefined callback + * @param hdsi dsi handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg HAL_DSI_TEARING_EFFECT_CB_ID Tearing Effect Callback ID + * @arg HAL_DSI_ENDOF_REFRESH_CB_ID End Of Refresh Callback ID + * @arg HAL_DSI_ERROR_CB_ID Error Callback ID + * @arg HAL_DSI_MSPINIT_CB_ID MspInit callback ID + * @arg HAL_DSI_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_DSI_RegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID, + pDSI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hdsi); + + if (hdsi->State == HAL_DSI_STATE_READY) + { + switch (CallbackID) + { + case HAL_DSI_TEARING_EFFECT_CB_ID : + hdsi->TearingEffectCallback = pCallback; + break; + + case HAL_DSI_ENDOF_REFRESH_CB_ID : + hdsi->EndOfRefreshCallback = pCallback; + break; + + case HAL_DSI_ERROR_CB_ID : + hdsi->ErrorCallback = pCallback; + break; + + case HAL_DSI_MSPINIT_CB_ID : + hdsi->MspInitCallback = pCallback; + break; + + case HAL_DSI_MSPDEINIT_CB_ID : + hdsi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hdsi->State == HAL_DSI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_DSI_MSPINIT_CB_ID : + hdsi->MspInitCallback = pCallback; + break; + + case HAL_DSI_MSPDEINIT_CB_ID : + hdsi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdsi); + + return status; +} + +/** + * @brief Unregister a DSI Callback + * DSI callback is redirected to the weak predefined callback + * @param hdsi dsi handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg HAL_DSI_TEARING_EFFECT_CB_ID Tearing Effect Callback ID + * @arg HAL_DSI_ENDOF_REFRESH_CB_ID End Of Refresh Callback ID + * @arg HAL_DSI_ERROR_CB_ID Error Callback ID + * @arg HAL_DSI_MSPINIT_CB_ID MspInit callback ID + * @arg HAL_DSI_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_DSI_UnRegisterCallback(DSI_HandleTypeDef *hdsi, HAL_DSI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hdsi); + + if (hdsi->State == HAL_DSI_STATE_READY) + { + switch (CallbackID) + { + case HAL_DSI_TEARING_EFFECT_CB_ID : + hdsi->TearingEffectCallback = HAL_DSI_TearingEffectCallback; /* Legacy weak TearingEffectCallback */ + break; + + case HAL_DSI_ENDOF_REFRESH_CB_ID : + hdsi->EndOfRefreshCallback = HAL_DSI_EndOfRefreshCallback; /* Legacy weak EndOfRefreshCallback */ + break; + + case HAL_DSI_ERROR_CB_ID : + hdsi->ErrorCallback = HAL_DSI_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_DSI_MSPINIT_CB_ID : + hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legacy weak MspInit Callback */ + break; + + case HAL_DSI_MSPDEINIT_CB_ID : + hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legacy weak MspDeInit Callback */ + break; + + default : + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hdsi->State == HAL_DSI_STATE_RESET) + { + switch (CallbackID) + { + case HAL_DSI_MSPINIT_CB_ID : + hdsi->MspInitCallback = HAL_DSI_MspInit; /* Legacy weak MspInit Callback */ + break; + + case HAL_DSI_MSPDEINIT_CB_ID : + hdsi->MspDeInitCallback = HAL_DSI_MspDeInit; /* Legacy weak MspDeInit Callback */ + break; + + default : + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hdsi->ErrorCode |= HAL_DSI_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hdsi); + + return status; +} +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup DSI_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides function allowing to: + (+) Handle DSI interrupt request + +@endverbatim + * @{ + */ +/** + * @brief Handles DSI interrupt request. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +void HAL_DSI_IRQHandler(DSI_HandleTypeDef *hdsi) +{ + uint32_t ErrorStatus0; + uint32_t ErrorStatus1; + + /* Tearing Effect Interrupt management ***************************************/ + if (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_TE) != 0U) + { + if (__HAL_DSI_GET_IT_SOURCE(hdsi, DSI_IT_TE) != 0U) + { + /* Clear the Tearing Effect Interrupt Flag */ + __HAL_DSI_CLEAR_FLAG(hdsi, DSI_FLAG_TE); + + /* Tearing Effect Callback */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + /*Call registered Tearing Effect callback */ + hdsi->TearingEffectCallback(hdsi); +#else + /*Call legacy Tearing Effect callback*/ + HAL_DSI_TearingEffectCallback(hdsi); +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + } + } + + /* End of Refresh Interrupt management ***************************************/ + if (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_ER) != 0U) + { + if (__HAL_DSI_GET_IT_SOURCE(hdsi, DSI_IT_ER) != 0U) + { + /* Clear the End of Refresh Interrupt Flag */ + __HAL_DSI_CLEAR_FLAG(hdsi, DSI_FLAG_ER); + + /* End of Refresh Callback */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + /*Call registered End of refresh callback */ + hdsi->EndOfRefreshCallback(hdsi); +#else + /*Call Legacy End of refresh callback */ + HAL_DSI_EndOfRefreshCallback(hdsi); +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + } + } + + /* Error Interrupts management ***********************************************/ + if (hdsi->ErrorMsk != 0U) + { + ErrorStatus0 = hdsi->Instance->ISR[0U]; + ErrorStatus0 &= hdsi->Instance->IER[0U]; + ErrorStatus1 = hdsi->Instance->ISR[1U]; + ErrorStatus1 &= hdsi->Instance->IER[1U]; + + if ((ErrorStatus0 & DSI_ERROR_ACK_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_ACK; + } + + if ((ErrorStatus0 & DSI_ERROR_PHY_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_PHY; + } + + if ((ErrorStatus1 & DSI_ERROR_TX_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_TX; + } + + if ((ErrorStatus1 & DSI_ERROR_RX_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_RX; + } + + if ((ErrorStatus1 & DSI_ERROR_ECC_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_ECC; + } + + if ((ErrorStatus1 & DSI_ERROR_CRC_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_CRC; + } + + if ((ErrorStatus1 & DSI_ERROR_PSE_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_PSE; + } + + if ((ErrorStatus1 & DSI_ERROR_EOT_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_EOT; + } + + if ((ErrorStatus1 & DSI_ERROR_OVF_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_OVF; + } + + if ((ErrorStatus1 & DSI_ERROR_GEN_MASK) != 0U) + { + hdsi->ErrorCode |= HAL_DSI_ERROR_GEN; + } + + /* Check only selected errors */ + if (hdsi->ErrorCode != HAL_DSI_ERROR_NONE) + { + /* DSI error interrupt callback */ +#if (USE_HAL_DSI_REGISTER_CALLBACKS == 1) + /*Call registered Error callback */ + hdsi->ErrorCallback(hdsi); +#else + /*Call Legacy Error callback */ + HAL_DSI_ErrorCallback(hdsi); +#endif /* USE_HAL_DSI_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief Tearing Effect DSI callback. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval None + */ +__weak void HAL_DSI_TearingEffectCallback(DSI_HandleTypeDef *hdsi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdsi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DSI_TearingEffectCallback could be implemented in the user file + */ +} + +/** + * @brief End of Refresh DSI callback. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval None + */ +__weak void HAL_DSI_EndOfRefreshCallback(DSI_HandleTypeDef *hdsi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdsi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DSI_EndOfRefreshCallback could be implemented in the user file + */ +} + +/** + * @brief Operation Error DSI callback. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval None + */ +__weak void HAL_DSI_ErrorCallback(DSI_HandleTypeDef *hdsi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdsi); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_DSI_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup DSI_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the Generic interface read-back Virtual Channel ID + (+) Select video mode and configure the corresponding parameters + (+) Configure command transmission mode: High-speed or Low-power + (+) Configure the flow control + (+) Configure the DSI PHY timer + (+) Configure the DSI HOST timeout + (+) Configure the DSI HOST timeout + (+) Start/Stop the DSI module + (+) Refresh the display in command mode + (+) Controls the display color mode in Video mode + (+) Control the display shutdown in Video mode + (+) write short DCS or short Generic command + (+) write long DCS or long Generic command + (+) Read command (DCS or generic) + (+) Enter/Exit the Ultra Low Power Mode on data only (D-PHY PLL running) + (+) Enter/Exit the Ultra Low Power Mode on data only and clock (D-PHY PLL turned off) + (+) Start/Stop test pattern generation + (+) Slew-Rate And Delay Tuning + (+) Low-Power Reception Filter Tuning + (+) Activate an additional current path on all lanes to meet the SDDTx parameter + (+) Custom lane pins configuration + (+) Set custom timing for the PHY + (+) Force the Clock/Data Lane in TX Stop Mode + (+) Force LP Receiver in Low-Power Mode + (+) Force Data Lanes in RX Mode after a BTA + (+) Enable a pull-down on the lanes to prevent from floating states when unused + (+) Switch off the contention detection on data lanes + +@endverbatim + * @{ + */ + +/** + * @brief Configure the Generic interface read-back Virtual Channel ID. + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param VirtualChannelID Virtual channel ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetGenericVCID(DSI_HandleTypeDef *hdsi, uint32_t VirtualChannelID) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Update the GVCID register */ + hdsi->Instance->GVCIDR &= ~DSI_GVCIDR_VCID; + hdsi->Instance->GVCIDR |= VirtualChannelID; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Select video mode and configure the corresponding parameters + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param VidCfg pointer to a DSI_VidCfgTypeDef structure that contains + * the DSI video mode configuration parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigVideoMode(DSI_HandleTypeDef *hdsi, DSI_VidCfgTypeDef *VidCfg) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_COLOR_CODING(VidCfg->ColorCoding)); + assert_param(IS_DSI_VIDEO_MODE_TYPE(VidCfg->Mode)); + assert_param(IS_DSI_LP_COMMAND(VidCfg->LPCommandEnable)); + assert_param(IS_DSI_LP_HFP(VidCfg->LPHorizontalFrontPorchEnable)); + assert_param(IS_DSI_LP_HBP(VidCfg->LPHorizontalBackPorchEnable)); + assert_param(IS_DSI_LP_VACTIVE(VidCfg->LPVerticalActiveEnable)); + assert_param(IS_DSI_LP_VFP(VidCfg->LPVerticalFrontPorchEnable)); + assert_param(IS_DSI_LP_VBP(VidCfg->LPVerticalBackPorchEnable)); + assert_param(IS_DSI_LP_VSYNC(VidCfg->LPVerticalSyncActiveEnable)); + assert_param(IS_DSI_FBTAA(VidCfg->FrameBTAAcknowledgeEnable)); + assert_param(IS_DSI_DE_POLARITY(VidCfg->DEPolarity)); + assert_param(IS_DSI_VSYNC_POLARITY(VidCfg->VSPolarity)); + assert_param(IS_DSI_HSYNC_POLARITY(VidCfg->HSPolarity)); + /* Check the LooselyPacked variant only in 18-bit mode */ + if (VidCfg->ColorCoding == DSI_RGB666) + { + assert_param(IS_DSI_LOOSELY_PACKED(VidCfg->LooselyPacked)); + } + + /* Select video mode by resetting CMDM and DSIM bits */ + hdsi->Instance->MCR &= ~DSI_MCR_CMDM; + hdsi->Instance->WCFGR &= ~DSI_WCFGR_DSIM; + + /* Configure the video mode transmission type */ + hdsi->Instance->VMCR &= ~DSI_VMCR_VMT; + hdsi->Instance->VMCR |= VidCfg->Mode; + + /* Configure the video packet size */ + hdsi->Instance->VPCR &= ~DSI_VPCR_VPSIZE; + hdsi->Instance->VPCR |= VidCfg->PacketSize; + + /* Set the chunks number to be transmitted through the DSI link */ + hdsi->Instance->VCCR &= ~DSI_VCCR_NUMC; + hdsi->Instance->VCCR |= VidCfg->NumberOfChunks; + + /* Set the size of the null packet */ + hdsi->Instance->VNPCR &= ~DSI_VNPCR_NPSIZE; + hdsi->Instance->VNPCR |= VidCfg->NullPacketSize; + + /* Select the virtual channel for the LTDC interface traffic */ + hdsi->Instance->LVCIDR &= ~DSI_LVCIDR_VCID; + hdsi->Instance->LVCIDR |= VidCfg->VirtualChannelID; + + /* Configure the polarity of control signals */ + hdsi->Instance->LPCR &= ~(DSI_LPCR_DEP | DSI_LPCR_VSP | DSI_LPCR_HSP); + hdsi->Instance->LPCR |= (VidCfg->DEPolarity | VidCfg->VSPolarity | VidCfg->HSPolarity); + + /* Select the color coding for the host */ + hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_COLC; + hdsi->Instance->LCOLCR |= VidCfg->ColorCoding; + + /* Select the color coding for the wrapper */ + hdsi->Instance->WCFGR &= ~DSI_WCFGR_COLMUX; + hdsi->Instance->WCFGR |= ((VidCfg->ColorCoding) << 1U); + + /* Enable/disable the loosely packed variant to 18-bit configuration */ + if (VidCfg->ColorCoding == DSI_RGB666) + { + hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_LPE; + hdsi->Instance->LCOLCR |= VidCfg->LooselyPacked; + } + + /* Set the Horizontal Synchronization Active (HSA) in lane byte clock cycles */ + hdsi->Instance->VHSACR &= ~DSI_VHSACR_HSA; + hdsi->Instance->VHSACR |= VidCfg->HorizontalSyncActive; + + /* Set the Horizontal Back Porch (HBP) in lane byte clock cycles */ + hdsi->Instance->VHBPCR &= ~DSI_VHBPCR_HBP; + hdsi->Instance->VHBPCR |= VidCfg->HorizontalBackPorch; + + /* Set the total line time (HLINE=HSA+HBP+HACT+HFP) in lane byte clock cycles */ + hdsi->Instance->VLCR &= ~DSI_VLCR_HLINE; + hdsi->Instance->VLCR |= VidCfg->HorizontalLine; + + /* Set the Vertical Synchronization Active (VSA) */ + hdsi->Instance->VVSACR &= ~DSI_VVSACR_VSA; + hdsi->Instance->VVSACR |= VidCfg->VerticalSyncActive; + + /* Set the Vertical Back Porch (VBP)*/ + hdsi->Instance->VVBPCR &= ~DSI_VVBPCR_VBP; + hdsi->Instance->VVBPCR |= VidCfg->VerticalBackPorch; + + /* Set the Vertical Front Porch (VFP)*/ + hdsi->Instance->VVFPCR &= ~DSI_VVFPCR_VFP; + hdsi->Instance->VVFPCR |= VidCfg->VerticalFrontPorch; + + /* Set the Vertical Active period*/ + hdsi->Instance->VVACR &= ~DSI_VVACR_VA; + hdsi->Instance->VVACR |= VidCfg->VerticalActive; + + /* Configure the command transmission mode */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPCE; + hdsi->Instance->VMCR |= VidCfg->LPCommandEnable; + + /* Low power largest packet size */ + hdsi->Instance->LPMCR &= ~DSI_LPMCR_LPSIZE; + hdsi->Instance->LPMCR |= ((VidCfg->LPLargestPacketSize) << 16U); + + /* Low power VACT largest packet size */ + hdsi->Instance->LPMCR &= ~DSI_LPMCR_VLPSIZE; + hdsi->Instance->LPMCR |= VidCfg->LPVACTLargestPacketSize; + + /* Enable LP transition in HFP period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPHFPE; + hdsi->Instance->VMCR |= VidCfg->LPHorizontalFrontPorchEnable; + + /* Enable LP transition in HBP period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPHBPE; + hdsi->Instance->VMCR |= VidCfg->LPHorizontalBackPorchEnable; + + /* Enable LP transition in VACT period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPVAE; + hdsi->Instance->VMCR |= VidCfg->LPVerticalActiveEnable; + + /* Enable LP transition in VFP period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPVFPE; + hdsi->Instance->VMCR |= VidCfg->LPVerticalFrontPorchEnable; + + /* Enable LP transition in VBP period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPVBPE; + hdsi->Instance->VMCR |= VidCfg->LPVerticalBackPorchEnable; + + /* Enable LP transition in vertical sync period */ + hdsi->Instance->VMCR &= ~DSI_VMCR_LPVSAE; + hdsi->Instance->VMCR |= VidCfg->LPVerticalSyncActiveEnable; + + /* Enable the request for an acknowledge response at the end of a frame */ + hdsi->Instance->VMCR &= ~DSI_VMCR_FBTAAE; + hdsi->Instance->VMCR |= VidCfg->FrameBTAAcknowledgeEnable; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Select adapted command mode and configure the corresponding parameters + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param CmdCfg pointer to a DSI_CmdCfgTypeDef structure that contains + * the DSI command mode configuration parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigAdaptedCommandMode(DSI_HandleTypeDef *hdsi, DSI_CmdCfgTypeDef *CmdCfg) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_COLOR_CODING(CmdCfg->ColorCoding)); + assert_param(IS_DSI_TE_SOURCE(CmdCfg->TearingEffectSource)); + assert_param(IS_DSI_TE_POLARITY(CmdCfg->TearingEffectPolarity)); + assert_param(IS_DSI_AUTOMATIC_REFRESH(CmdCfg->AutomaticRefresh)); + assert_param(IS_DSI_VS_POLARITY(CmdCfg->VSyncPol)); + assert_param(IS_DSI_TE_ACK_REQUEST(CmdCfg->TEAcknowledgeRequest)); + assert_param(IS_DSI_DE_POLARITY(CmdCfg->DEPolarity)); + assert_param(IS_DSI_VSYNC_POLARITY(CmdCfg->VSPolarity)); + assert_param(IS_DSI_HSYNC_POLARITY(CmdCfg->HSPolarity)); + + /* Select command mode by setting CMDM and DSIM bits */ + hdsi->Instance->MCR |= DSI_MCR_CMDM; + hdsi->Instance->WCFGR &= ~DSI_WCFGR_DSIM; + hdsi->Instance->WCFGR |= DSI_WCFGR_DSIM; + + /* Select the virtual channel for the LTDC interface traffic */ + hdsi->Instance->LVCIDR &= ~DSI_LVCIDR_VCID; + hdsi->Instance->LVCIDR |= CmdCfg->VirtualChannelID; + + /* Configure the polarity of control signals */ + hdsi->Instance->LPCR &= ~(DSI_LPCR_DEP | DSI_LPCR_VSP | DSI_LPCR_HSP); + hdsi->Instance->LPCR |= (CmdCfg->DEPolarity | CmdCfg->VSPolarity | CmdCfg->HSPolarity); + + /* Select the color coding for the host */ + hdsi->Instance->LCOLCR &= ~DSI_LCOLCR_COLC; + hdsi->Instance->LCOLCR |= CmdCfg->ColorCoding; + + /* Select the color coding for the wrapper */ + hdsi->Instance->WCFGR &= ~DSI_WCFGR_COLMUX; + hdsi->Instance->WCFGR |= ((CmdCfg->ColorCoding) << 1U); + + /* Configure the maximum allowed size for write memory command */ + hdsi->Instance->LCCR &= ~DSI_LCCR_CMDSIZE; + hdsi->Instance->LCCR |= CmdCfg->CommandSize; + + /* Configure the tearing effect source and polarity and select the refresh mode */ + hdsi->Instance->WCFGR &= ~(DSI_WCFGR_TESRC | DSI_WCFGR_TEPOL | DSI_WCFGR_AR | DSI_WCFGR_VSPOL); + hdsi->Instance->WCFGR |= (CmdCfg->TearingEffectSource | CmdCfg->TearingEffectPolarity | CmdCfg->AutomaticRefresh | + CmdCfg->VSyncPol); + + /* Configure the tearing effect acknowledge request */ + hdsi->Instance->CMCR &= ~DSI_CMCR_TEARE; + hdsi->Instance->CMCR |= CmdCfg->TEAcknowledgeRequest; + + /* Enable the Tearing Effect interrupt */ + __HAL_DSI_ENABLE_IT(hdsi, DSI_IT_TE); + + /* Enable the End of Refresh interrupt */ + __HAL_DSI_ENABLE_IT(hdsi, DSI_IT_ER); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Configure command transmission mode: High-speed or Low-power + * and enable/disable acknowledge request after packet transmission + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param LPCmd pointer to a DSI_LPCmdTypeDef structure that contains + * the DSI command transmission mode configuration parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigCommand(DSI_HandleTypeDef *hdsi, DSI_LPCmdTypeDef *LPCmd) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + assert_param(IS_DSI_LP_GSW0P(LPCmd->LPGenShortWriteNoP)); + assert_param(IS_DSI_LP_GSW1P(LPCmd->LPGenShortWriteOneP)); + assert_param(IS_DSI_LP_GSW2P(LPCmd->LPGenShortWriteTwoP)); + assert_param(IS_DSI_LP_GSR0P(LPCmd->LPGenShortReadNoP)); + assert_param(IS_DSI_LP_GSR1P(LPCmd->LPGenShortReadOneP)); + assert_param(IS_DSI_LP_GSR2P(LPCmd->LPGenShortReadTwoP)); + assert_param(IS_DSI_LP_GLW(LPCmd->LPGenLongWrite)); + assert_param(IS_DSI_LP_DSW0P(LPCmd->LPDcsShortWriteNoP)); + assert_param(IS_DSI_LP_DSW1P(LPCmd->LPDcsShortWriteOneP)); + assert_param(IS_DSI_LP_DSR0P(LPCmd->LPDcsShortReadNoP)); + assert_param(IS_DSI_LP_DLW(LPCmd->LPDcsLongWrite)); + assert_param(IS_DSI_LP_MRDP(LPCmd->LPMaxReadPacket)); + assert_param(IS_DSI_ACK_REQUEST(LPCmd->AcknowledgeRequest)); + + /* Select High-speed or Low-power for command transmission */ + hdsi->Instance->CMCR &= ~(DSI_CMCR_GSW0TX | \ + DSI_CMCR_GSW1TX | \ + DSI_CMCR_GSW2TX | \ + DSI_CMCR_GSR0TX | \ + DSI_CMCR_GSR1TX | \ + DSI_CMCR_GSR2TX | \ + DSI_CMCR_GLWTX | \ + DSI_CMCR_DSW0TX | \ + DSI_CMCR_DSW1TX | \ + DSI_CMCR_DSR0TX | \ + DSI_CMCR_DLWTX | \ + DSI_CMCR_MRDPS); + hdsi->Instance->CMCR |= (LPCmd->LPGenShortWriteNoP | \ + LPCmd->LPGenShortWriteOneP | \ + LPCmd->LPGenShortWriteTwoP | \ + LPCmd->LPGenShortReadNoP | \ + LPCmd->LPGenShortReadOneP | \ + LPCmd->LPGenShortReadTwoP | \ + LPCmd->LPGenLongWrite | \ + LPCmd->LPDcsShortWriteNoP | \ + LPCmd->LPDcsShortWriteOneP | \ + LPCmd->LPDcsShortReadNoP | \ + LPCmd->LPDcsLongWrite | \ + LPCmd->LPMaxReadPacket); + + /* Configure the acknowledge request after each packet transmission */ + hdsi->Instance->CMCR &= ~DSI_CMCR_ARE; + hdsi->Instance->CMCR |= LPCmd->AcknowledgeRequest; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Configure the flow control parameters + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param FlowControl flow control feature(s) to be enabled. + * This parameter can be any combination of @arg DSI_FlowControl. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigFlowControl(DSI_HandleTypeDef *hdsi, uint32_t FlowControl) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_FLOW_CONTROL(FlowControl)); + + /* Set the DSI Host Protocol Configuration Register */ + hdsi->Instance->PCR &= ~DSI_FLOW_CONTROL_ALL; + hdsi->Instance->PCR |= FlowControl; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Configure the DSI PHY timer parameters + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param PhyTimers DSI_PHY_TimerTypeDef structure that contains + * the DSI PHY timing parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigPhyTimer(DSI_HandleTypeDef *hdsi, DSI_PHY_TimerTypeDef *PhyTimers) +{ + uint32_t maxTime; + /* Process locked */ + __HAL_LOCK(hdsi); + + maxTime = (PhyTimers->ClockLaneLP2HSTime > PhyTimers->ClockLaneHS2LPTime) ? PhyTimers->ClockLaneLP2HSTime : + PhyTimers->ClockLaneHS2LPTime; + + /* Clock lane timer configuration */ + + /* In Automatic Clock Lane control mode, the DSI Host can turn off the clock lane between two + High-Speed transmission. + To do so, the DSI Host calculates the time required for the clock lane to change from HighSpeed + to Low-Power and from Low-Power to High-Speed. + This timings are configured by the HS2LP_TIME and LP2HS_TIME in the DSI Host Clock Lane Timer Configuration + Register (DSI_CLTCR). + But the DSI Host is not calculating LP2HS_TIME + HS2LP_TIME but 2 x HS2LP_TIME. + + Workaround : Configure HS2LP_TIME and LP2HS_TIME with the same value being the max of HS2LP_TIME or LP2HS_TIME. + */ + hdsi->Instance->CLTCR &= ~(DSI_CLTCR_LP2HS_TIME | DSI_CLTCR_HS2LP_TIME); + hdsi->Instance->CLTCR |= (maxTime | ((maxTime) << 16U)); + + /* Data lane timer configuration */ + hdsi->Instance->DLTCR &= ~(DSI_DLTCR_MRD_TIME | DSI_DLTCR_LP2HS_TIME | DSI_DLTCR_HS2LP_TIME); + hdsi->Instance->DLTCR |= (PhyTimers->DataLaneMaxReadTime | ((PhyTimers->DataLaneLP2HSTime) << 16U) | (( + PhyTimers->DataLaneHS2LPTime) << 24U)); + + /* Configure the wait period to request HS transmission after a stop state */ + hdsi->Instance->PCONFR &= ~DSI_PCONFR_SW_TIME; + hdsi->Instance->PCONFR |= ((PhyTimers->StopWaitTime) << 8U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Configure the DSI HOST timeout parameters + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param HostTimeouts DSI_HOST_TimeoutTypeDef structure that contains + * the DSI host timeout parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ConfigHostTimeouts(DSI_HandleTypeDef *hdsi, DSI_HOST_TimeoutTypeDef *HostTimeouts) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Set the timeout clock division factor */ + hdsi->Instance->CCR &= ~DSI_CCR_TOCKDIV; + hdsi->Instance->CCR |= ((HostTimeouts->TimeoutCkdiv) << 8U); + + /* High-speed transmission timeout */ + hdsi->Instance->TCCR[0U] &= ~DSI_TCCR0_HSTX_TOCNT; + hdsi->Instance->TCCR[0U] |= ((HostTimeouts->HighSpeedTransmissionTimeout) << 16U); + + /* Low-power reception timeout */ + hdsi->Instance->TCCR[0U] &= ~DSI_TCCR0_LPRX_TOCNT; + hdsi->Instance->TCCR[0U] |= HostTimeouts->LowPowerReceptionTimeout; + + /* High-speed read timeout */ + hdsi->Instance->TCCR[1U] &= ~DSI_TCCR1_HSRD_TOCNT; + hdsi->Instance->TCCR[1U] |= HostTimeouts->HighSpeedReadTimeout; + + /* Low-power read timeout */ + hdsi->Instance->TCCR[2U] &= ~DSI_TCCR2_LPRD_TOCNT; + hdsi->Instance->TCCR[2U] |= HostTimeouts->LowPowerReadTimeout; + + /* High-speed write timeout */ + hdsi->Instance->TCCR[3U] &= ~DSI_TCCR3_HSWR_TOCNT; + hdsi->Instance->TCCR[3U] |= HostTimeouts->HighSpeedWriteTimeout; + + /* High-speed write presp mode */ + hdsi->Instance->TCCR[3U] &= ~DSI_TCCR3_PM; + hdsi->Instance->TCCR[3U] |= HostTimeouts->HighSpeedWritePrespMode; + + /* Low-speed write timeout */ + hdsi->Instance->TCCR[4U] &= ~DSI_TCCR4_LPWR_TOCNT; + hdsi->Instance->TCCR[4U] |= HostTimeouts->LowPowerWriteTimeout; + + /* BTA timeout */ + hdsi->Instance->TCCR[5U] &= ~DSI_TCCR5_BTA_TOCNT; + hdsi->Instance->TCCR[5U] |= HostTimeouts->BTATimeout; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Start the DSI module + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Start(DSI_HandleTypeDef *hdsi) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Enable the DSI host */ + __HAL_DSI_ENABLE(hdsi); + + /* Enable the DSI wrapper */ + __HAL_DSI_WRAPPER_ENABLE(hdsi); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Stop the DSI module + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Stop(DSI_HandleTypeDef *hdsi) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Disable the DSI host */ + __HAL_DSI_DISABLE(hdsi); + + /* Disable the DSI wrapper */ + __HAL_DSI_WRAPPER_DISABLE(hdsi); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Refresh the display in command mode + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Refresh(DSI_HandleTypeDef *hdsi) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Update the display */ + hdsi->Instance->WCR |= DSI_WCR_LTDCEN; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Controls the display color mode in Video mode + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ColorMode Color mode (full or 8-colors). + * This parameter can be any value of @arg DSI_Color_Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ColorMode(DSI_HandleTypeDef *hdsi, uint32_t ColorMode) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_COLOR_MODE(ColorMode)); + + /* Update the display color mode */ + hdsi->Instance->WCR &= ~DSI_WCR_COLM; + hdsi->Instance->WCR |= ColorMode; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Control the display shutdown in Video mode + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param Shutdown Shut-down (Display-ON or Display-OFF). + * This parameter can be any value of @arg DSI_ShutDown + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Shutdown(DSI_HandleTypeDef *hdsi, uint32_t Shutdown) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_SHUT_DOWN(Shutdown)); + + /* Update the display Shutdown */ + hdsi->Instance->WCR &= ~DSI_WCR_SHTDN; + hdsi->Instance->WCR |= Shutdown; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief write short DCS or short Generic command + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ChannelID Virtual channel ID. + * @param Mode DSI short packet data type. + * This parameter can be any value of @arg DSI_SHORT_WRITE_PKT_Data_Type. + * @param Param1 DSC command or first generic parameter. + * This parameter can be any value of @arg DSI_DCS_Command or a + * generic command code. + * @param Param2 DSC parameter or second generic parameter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ShortWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t Param1, + uint32_t Param2) +{ + HAL_StatusTypeDef status; + /* Check the parameters */ + assert_param(IS_DSI_SHORT_WRITE_PACKET_TYPE(Mode)); + + /* Process locked */ + __HAL_LOCK(hdsi); + + status = DSI_ShortWrite(hdsi, ChannelID, Mode, Param1, Param2); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return status; +} + +/** + * @brief write long DCS or long Generic command + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ChannelID Virtual channel ID. + * @param Mode DSI long packet data type. + * This parameter can be any value of @arg DSI_LONG_WRITE_PKT_Data_Type. + * @param NbParams Number of parameters. + * @param Param1 DSC command or first generic parameter. + * This parameter can be any value of @arg DSI_DCS_Command or a + * generic command code + * @param ParametersTable Pointer to parameter values table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_LongWrite(DSI_HandleTypeDef *hdsi, + uint32_t ChannelID, + uint32_t Mode, + uint32_t NbParams, + uint32_t Param1, + uint8_t *ParametersTable) +{ + uint32_t uicounter; + uint32_t nbBytes; + uint32_t count; + uint32_t tickstart; + uint32_t fifoword; + uint8_t *pparams = ParametersTable; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_LONG_WRITE_PACKET_TYPE(Mode)); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for Command FIFO Empty */ + while ((hdsi->Instance->GPSR & DSI_GPSR_CMDFE) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Set the DCS code on payload byte 1, and the other parameters on the write FIFO command*/ + fifoword = Param1; + nbBytes = (NbParams < 3U) ? NbParams : 3U; + + for (count = 0U; count < nbBytes; count++) + { + fifoword |= (((uint32_t)(*(pparams + count))) << (8U + (8U * count))); + } + hdsi->Instance->GPDR = fifoword; + + uicounter = NbParams - nbBytes; + pparams += nbBytes; + /* Set the Next parameters on the write FIFO command*/ + while (uicounter != 0U) + { + nbBytes = (uicounter < 4U) ? uicounter : 4U; + fifoword = 0U; + for (count = 0U; count < nbBytes; count++) + { + fifoword |= (((uint32_t)(*(pparams + count))) << (8U * count)); + } + hdsi->Instance->GPDR = fifoword; + + uicounter -= nbBytes; + pparams += nbBytes; + } + + /* Configure the packet to send a long DCS command */ + DSI_ConfigPacketHeader(hdsi->Instance, + ChannelID, + Mode, + ((NbParams + 1U) & 0x00FFU), + (((NbParams + 1U) & 0xFF00U) >> 8U)); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Read command (DCS or generic) + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param ChannelNbr Virtual channel ID + * @param Array pointer to a buffer to store the payload of a read back operation. + * @param Size Data size to be read (in byte). + * @param Mode DSI read packet data type. + * This parameter can be any value of @arg DSI_SHORT_READ_PKT_Data_Type. + * @param DCSCmd DCS get/read command. + * @param ParametersTable Pointer to parameter values table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_Read(DSI_HandleTypeDef *hdsi, + uint32_t ChannelNbr, + uint8_t *Array, + uint32_t Size, + uint32_t Mode, + uint32_t DCSCmd, + uint8_t *ParametersTable) +{ + uint32_t tickstart; + uint8_t *pdata = Array; + uint32_t datasize = Size; + uint32_t fifoword; + uint32_t nbbytes; + uint32_t count; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check the parameters */ + assert_param(IS_DSI_READ_PACKET_TYPE(Mode)); + + if (datasize > 2U) + { + /* set max return packet size */ + if (DSI_ShortWrite(hdsi, ChannelNbr, DSI_MAX_RETURN_PKT_SIZE, ((datasize) & 0xFFU), + (((datasize) >> 8U) & 0xFFU)) != HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + + /* Configure the packet to read command */ + if (Mode == DSI_DCS_SHORT_PKT_READ) + { + DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, DCSCmd, 0U); + } + else if (Mode == DSI_GEN_SHORT_PKT_READ_P0) + { + DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, 0U, 0U); + } + else if (Mode == DSI_GEN_SHORT_PKT_READ_P1) + { + DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, ParametersTable[0U], 0U); + } + else if (Mode == DSI_GEN_SHORT_PKT_READ_P2) + { + DSI_ConfigPacketHeader(hdsi->Instance, ChannelNbr, Mode, ParametersTable[0U], ParametersTable[1U]); + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* If DSI fifo is not empty, read requested bytes */ + while (((int32_t)(datasize)) > 0) + { + if ((hdsi->Instance->GPSR & DSI_GPSR_PRDFE) == 0U) + { + fifoword = hdsi->Instance->GPDR; + nbbytes = (datasize < 4U) ? datasize : 4U; + + for (count = 0U; count < nbbytes; count++) + { + *pdata = (uint8_t)(fifoword >> (8U * count)); + pdata++; + datasize--; + } + } + + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + + /* Software workaround to avoid HAL_TIMEOUT when a DSI read command is */ + /* issued to the panel and the read data is not captured by the DSI Host */ + /* which returns Packet Size Error. */ + /* Need to ensure that the Read command has finished before checking PSE */ + if ((hdsi->Instance->GPSR & DSI_GPSR_RCB) == 0U) + { + if ((hdsi->Instance->ISR[1U] & DSI_ISR1_PSE) == DSI_ISR1_PSE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Enter the ULPM (Ultra Low Power Mode) with the D-PHY PLL running + * (only data lanes are in ULPM) + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_EnterULPMData(DSI_HandleTypeDef *hdsi) +{ + uint32_t tickstart; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Verify the initial status of the DSI Host */ + + /* Verify that the clock lane and the digital section of the D-PHY are enabled */ + if ((hdsi->Instance->PCTLR & (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) != (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that the D-PHY PLL and the reference bias are enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no ULPS exit or request on data lanes */ + if ((hdsi->Instance->PUCR & (DSI_PUCR_UEDL | DSI_PUCR_URDL)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no Transmission trigger */ + if ((hdsi->Instance->PTTCR & DSI_PTTCR_TX_TRIG) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Verify that D-PHY PLL is locked */ + tickstart = HAL_GetTick(); + + while ((__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* ULPS Request on Data Lanes */ + hdsi->Instance->PUCR |= DSI_PUCR_URDL; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until the D-PHY active lanes enter into ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + while ((hdsi->Instance->PSR & DSI_PSR_UAN0) != 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Exit the ULPM (Ultra Low Power Mode) with the D-PHY PLL running + * (only data lanes are in ULPM) + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ExitULPMData(DSI_HandleTypeDef *hdsi) +{ + uint32_t tickstart; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Verify that all active lanes are in ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Turn on the DSI PLL */ + __HAL_DSI_PLL_ENABLE(hdsi); + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Exit ULPS on Data Lanes */ + hdsi->Instance->PUCR |= DSI_PUCR_UEDL; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until all active lanes exit ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + while ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* wait for 1 ms*/ + HAL_Delay(1U); + + /* De-assert the ULPM requests and the ULPM exit bits */ + hdsi->Instance->PUCR = 0U; + + /* Verify that D-PHY PLL is enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & DSI_PSR_UAN0) != DSI_PSR_UAN0) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that D-PHY PLL is locked */ + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Enter the ULPM (Ultra Low Power Mode) with the D-PHY PLL turned off + * (both data and clock lanes are in ULPM) + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_EnterULPM(DSI_HandleTypeDef *hdsi) +{ + uint32_t tickstart; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Verify the initial status of the DSI Host */ + + /* Verify that the clock lane and the digital section of the D-PHY are enabled */ + if ((hdsi->Instance->PCTLR & (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) != (DSI_PCTLR_CKE | DSI_PCTLR_DEN)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that the D-PHY PLL and the reference bias are enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no ULPS exit or request on both data and clock lanes */ + if ((hdsi->Instance->PUCR & (DSI_PUCR_UEDL | DSI_PUCR_URDL | DSI_PUCR_UECL | DSI_PUCR_URCL)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that there are no Transmission trigger */ + if ((hdsi->Instance->PTTCR & DSI_PTTCR_TX_TRIG) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Verify that D-PHY PLL is locked */ + tickstart = HAL_GetTick(); + + while ((__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | \ + DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Clock lane configuration: no more HS request */ + hdsi->Instance->CLCR &= ~DSI_CLCR_DPCC; + + /* Use system PLL as byte lane clock source before stopping DSIPHY clock source */ + __HAL_RCC_DSI_CONFIG(RCC_DSICLKSOURCE_PLLR); + + /* ULPS Request on Clock and Data Lanes */ + hdsi->Instance->PUCR |= (DSI_PUCR_URCL | DSI_PUCR_URDL); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until all active lanes enter ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UANC)) != 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1 | DSI_PSR_UANC)) != 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Turn off the DSI PLL */ + __HAL_DSI_PLL_DISABLE(hdsi); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Exit the ULPM (Ultra Low Power Mode) with the D-PHY PLL turned off + * (both data and clock lanes are in ULPM) + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ExitULPM(DSI_HandleTypeDef *hdsi) +{ + uint32_t tickstart; + + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Verify that all active lanes are in ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_RUE0 | DSI_PSR_UAN0 | DSI_PSR_PSS0 | \ + DSI_PSR_UANC | DSI_PSR_PSSC | DSI_PSR_PD)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_RUE0 | DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_UAN1 | \ + DSI_PSR_PSS1 | DSI_PSR_UANC | DSI_PSR_PSSC | DSI_PSR_PD)) != 0U) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Turn on the DSI PLL */ + __HAL_DSI_PLL_ENABLE(hdsi); + + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Exit ULPS on Clock and Data Lanes */ + hdsi->Instance->PUCR |= (DSI_PUCR_UECL | DSI_PUCR_UEDL); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until all active lanes exit ULPM */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UANC)) != (DSI_PSR_UAN0 | DSI_PSR_UANC)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + while ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_UAN1 | DSI_PSR_UANC)) != (DSI_PSR_UAN0 | DSI_PSR_UAN1 | + DSI_PSR_UANC)) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* wait for 1 ms */ + HAL_Delay(1U); + + /* De-assert the ULPM requests and the ULPM exit bits */ + hdsi->Instance->PUCR = 0U; + + /* Switch the lane byte clock source in the RCC from system PLL to D-PHY */ + __HAL_RCC_DSI_CONFIG(RCC_DSICLKSOURCE_DSIPHY); + + /* Restore clock lane configuration to HS */ + hdsi->Instance->CLCR |= DSI_CLCR_DPCC; + + /* Verify that D-PHY PLL is enabled */ + if ((hdsi->Instance->WRPCR & DSI_WRPCR_PLLEN) != DSI_WRPCR_PLLEN) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that all active lanes are in Stop state */ + if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_ONE_DATA_LANE) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else if ((hdsi->Instance->PCONFR & DSI_PCONFR_NL) == DSI_TWO_DATA_LANES) + { + if ((hdsi->Instance->PSR & (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | \ + DSI_PSR_UAN1)) != (DSI_PSR_UAN0 | DSI_PSR_PSS0 | DSI_PSR_PSS1 | DSI_PSR_UAN1)) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + return HAL_ERROR; + } + + /* Verify that D-PHY PLL is locked */ + /* Requires min of 400us delay before reading the PLLLS flag */ + /* 1ms delay is inserted that is the minimum HAL delay granularity */ + HAL_Delay(1); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for the lock of the PLL */ + while (__HAL_DSI_GET_FLAG(hdsi, DSI_FLAG_PLLLS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > DSI_TIMEOUT_VALUE) + { + /* Process Unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_TIMEOUT; + } + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Start test pattern generation + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param Mode Pattern generator mode + * This parameter can be one of the following values: + * 0 : Color bars (horizontal or vertical) + * 1 : BER pattern (vertical only) + * @param Orientation Pattern generator orientation + * This parameter can be one of the following values: + * 0 : Vertical color bars + * 1 : Horizontal color bars + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_PatternGeneratorStart(DSI_HandleTypeDef *hdsi, uint32_t Mode, uint32_t Orientation) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Configure pattern generator mode and orientation */ + hdsi->Instance->VMCR &= ~(DSI_VMCR_PGM | DSI_VMCR_PGO); + hdsi->Instance->VMCR |= ((Mode << 20U) | (Orientation << 24U)); + + /* Enable pattern generator by setting PGE bit */ + hdsi->Instance->VMCR |= DSI_VMCR_PGE; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Stop test pattern generation + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_PatternGeneratorStop(DSI_HandleTypeDef *hdsi) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Disable pattern generator by clearing PGE bit */ + hdsi->Instance->VMCR &= ~DSI_VMCR_PGE; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Set Slew-Rate And Delay Tuning + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param CommDelay Communication delay to be adjusted. + * This parameter can be any value of @arg DSI_Communication_Delay + * @param Lane select between clock or data lanes. + * This parameter can be any value of @arg DSI_Lane_Group + * @param Value Custom value of the slew-rate or delay + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetSlewRateAndDelayTuning(DSI_HandleTypeDef *hdsi, uint32_t CommDelay, uint32_t Lane, + uint32_t Value) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_DSI_COMMUNICATION_DELAY(CommDelay)); + assert_param(IS_DSI_LANE_GROUP(Lane)); + + switch (CommDelay) + { + case DSI_SLEW_RATE_HSTX: + if (Lane == DSI_CLOCK_LANE) + { + /* High-Speed Transmission Slew Rate Control on Clock Lane */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXSRCCL; + hdsi->Instance->WPCR[1U] |= Value << 16U; + } + else if (Lane == DSI_DATA_LANES) + { + /* High-Speed Transmission Slew Rate Control on Data Lanes */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXSRCDL; + hdsi->Instance->WPCR[1U] |= Value << 18U; + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + break; + case DSI_SLEW_RATE_LPTX: + if (Lane == DSI_CLOCK_LANE) + { + /* Low-Power transmission Slew Rate Compensation on Clock Lane */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPSRCCL; + hdsi->Instance->WPCR[1U] |= Value << 6U; + } + else if (Lane == DSI_DATA_LANES) + { + /* Low-Power transmission Slew Rate Compensation on Data Lanes */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPSRCDL; + hdsi->Instance->WPCR[1U] |= Value << 8U; + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + break; + case DSI_HS_DELAY: + if (Lane == DSI_CLOCK_LANE) + { + /* High-Speed Transmission Delay on Clock Lane */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXDCL; + hdsi->Instance->WPCR[1U] |= Value; + } + else if (Lane == DSI_DATA_LANES) + { + /* High-Speed Transmission Delay on Data Lanes */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_HSTXDDL; + hdsi->Instance->WPCR[1U] |= Value << 2U; + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + break; + default: + break; + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Low-Power Reception Filter Tuning + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param Frequency cutoff frequency of low-pass filter at the input of LPRX + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetLowPowerRXFilter(DSI_HandleTypeDef *hdsi, uint32_t Frequency) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Low-Power RX low-pass Filtering Tuning */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_LPRXFT; + hdsi->Instance->WPCR[1U] |= Frequency << 25U; + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Activate an additional current path on all lanes to meet the SDDTx parameter + * defined in the MIPI D-PHY specification + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetSDD(DSI_HandleTypeDef *hdsi, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_FUNCTIONAL_STATE(State)); + + /* Activate/Disactivate additional current path on all lanes */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_SDDC; + hdsi->Instance->WPCR[1U] |= ((uint32_t)State << 12U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Custom lane pins configuration + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param CustomLane Function to be applied on selected lane. + * This parameter can be any value of @arg DSI_CustomLane + * @param Lane select between clock or data lane 0 or data lane 1. + * This parameter can be any value of @arg DSI_Lane_Select + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetLanePinsConfiguration(DSI_HandleTypeDef *hdsi, uint32_t CustomLane, uint32_t Lane, + FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_DSI_CUSTOM_LANE(CustomLane)); + assert_param(IS_DSI_LANE(Lane)); + assert_param(IS_FUNCTIONAL_STATE(State)); + + switch (CustomLane) + { + case DSI_SWAP_LANE_PINS: + if (Lane == DSI_CLK_LANE) + { + /* Swap pins on clock lane */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWCL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 6U); + } + else if (Lane == DSI_DATA_LANE0) + { + /* Swap pins on data lane 0 */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWDL0; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 7U); + } + else if (Lane == DSI_DATA_LANE1) + { + /* Swap pins on data lane 1 */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_SWDL1; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 8U); + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + break; + case DSI_INVERT_HS_SIGNAL: + if (Lane == DSI_CLK_LANE) + { + /* Invert HS signal on clock lane */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSICL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 9U); + } + else if (Lane == DSI_DATA_LANE0) + { + /* Invert HS signal on data lane 0 */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSIDL0; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 10U); + } + else if (Lane == DSI_DATA_LANE1) + { + /* Invert HS signal on data lane 1 */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_HSIDL1; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 11U); + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + break; + default: + break; + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Set custom timing for the PHY + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param Timing PHY timing to be adjusted. + * This parameter can be any value of @arg DSI_PHY_Timing + * @param State ENABLE or DISABLE + * @param Value Custom value of the timing + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetPHYTimings(DSI_HandleTypeDef *hdsi, uint32_t Timing, FunctionalState State, uint32_t Value) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_DSI_PHY_TIMING(Timing)); + assert_param(IS_FUNCTIONAL_STATE(State)); + + switch (Timing) + { + case DSI_TCLK_POST: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKPOSTEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 27U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[4U] &= ~DSI_WPCR4_TCLKPOST; + hdsi->Instance->WPCR[4U] |= Value & DSI_WPCR4_TCLKPOST; + } + + break; + case DSI_TLPX_CLK: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TLPXCEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 26U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_TLPXC; + hdsi->Instance->WPCR[3U] |= (Value << 24U) & DSI_WPCR3_TLPXC; + } + + break; + case DSI_THS_EXIT: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSEXITEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 25U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_THSEXIT; + hdsi->Instance->WPCR[3U] |= (Value << 16U) & DSI_WPCR3_THSEXIT; + } + + break; + case DSI_TLPX_DATA: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TLPXDEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 24U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_TLPXD; + hdsi->Instance->WPCR[3U] |= (Value << 8U) & DSI_WPCR3_TLPXD; + } + + break; + case DSI_THS_ZERO: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSZEROEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 23U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[3U] &= ~DSI_WPCR3_THSZERO; + hdsi->Instance->WPCR[3U] |= Value & DSI_WPCR3_THSZERO; + } + + break; + case DSI_THS_TRAIL: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSTRAILEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 22U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_THSTRAIL; + hdsi->Instance->WPCR[2U] |= (Value << 24U) & DSI_WPCR2_THSTRAIL; + } + + break; + case DSI_THS_PREPARE: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_THSPREPEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 21U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_THSPREP; + hdsi->Instance->WPCR[2U] |= (Value << 16U) & DSI_WPCR2_THSPREP; + } + + break; + case DSI_TCLK_ZERO: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKZEROEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 20U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_TCLKZERO; + hdsi->Instance->WPCR[2U] |= (Value << 8U) & DSI_WPCR2_TCLKZERO; + } + + break; + case DSI_TCLK_PREPARE: + /* Enable/Disable custom timing setting */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TCLKPREPEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 19U); + + if (State != DISABLE) + { + /* Set custom value */ + hdsi->Instance->WPCR[2U] &= ~DSI_WPCR2_TCLKPREP; + hdsi->Instance->WPCR[2U] |= Value & DSI_WPCR2_TCLKPREP; + } + + break; + default: + break; + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Force the Clock/Data Lane in TX Stop Mode + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param Lane select between clock or data lanes. + * This parameter can be any value of @arg DSI_Lane_Group + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ForceTXStopMode(DSI_HandleTypeDef *hdsi, uint32_t Lane, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_DSI_LANE_GROUP(Lane)); + assert_param(IS_FUNCTIONAL_STATE(State)); + + if (Lane == DSI_CLOCK_LANE) + { + /* Force/Unforce the Clock Lane in TX Stop Mode */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_FTXSMCL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 12U); + } + else if (Lane == DSI_DATA_LANES) + { + /* Force/Unforce the Data Lanes in TX Stop Mode */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_FTXSMDL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 13U); + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_ERROR; + } + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Force LP Receiver in Low-Power Mode + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ForceRXLowPower(DSI_HandleTypeDef *hdsi, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_FUNCTIONAL_STATE(State)); + + /* Force/Unforce LP Receiver in Low-Power Mode */ + hdsi->Instance->WPCR[1U] &= ~DSI_WPCR1_FLPRXLPM; + hdsi->Instance->WPCR[1U] |= ((uint32_t)State << 22U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Force Data Lanes in RX Mode after a BTA + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_ForceDataLanesInRX(DSI_HandleTypeDef *hdsi, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_FUNCTIONAL_STATE(State)); + + /* Force Data Lanes in RX Mode */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_TDDL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 16U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Enable a pull-down on the lanes to prevent from floating states when unused + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetPullDown(DSI_HandleTypeDef *hdsi, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_FUNCTIONAL_STATE(State)); + + /* Enable/Disable pull-down on lanes */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_PDEN; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 18U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @brief Switch off the contention detection on data lanes + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @param State ENABLE or DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_DSI_SetContentionDetectionOff(DSI_HandleTypeDef *hdsi, FunctionalState State) +{ + /* Process locked */ + __HAL_LOCK(hdsi); + + /* Check function parameters */ + assert_param(IS_FUNCTIONAL_STATE(State)); + + /* Contention Detection on Data Lanes OFF */ + hdsi->Instance->WPCR[0U] &= ~DSI_WPCR0_CDOFFDL; + hdsi->Instance->WPCR[0U] |= ((uint32_t)State << 14U); + + /* Process unlocked */ + __HAL_UNLOCK(hdsi); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup DSI_Group4 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the DSI state. + (+) Get error code. + +@endverbatim + * @{ + */ + +/** + * @brief Return the DSI state + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval HAL state + */ +HAL_DSI_StateTypeDef HAL_DSI_GetState(DSI_HandleTypeDef *hdsi) +{ + return hdsi->State; +} + +/** + * @brief Return the DSI error code + * @param hdsi pointer to a DSI_HandleTypeDef structure that contains + * the configuration information for the DSI. + * @retval DSI Error Code + */ +uint32_t HAL_DSI_GetError(DSI_HandleTypeDef *hdsi) +{ + /* Get the error code */ + return hdsi->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DSI */ + +#endif /* HAL_DSI_MODULE_ENABLED */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c new file mode 100644 index 0000000..50d95b8 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_eth.c @@ -0,0 +1,3220 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and deinitialization 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 ETH HAL driver can be used as follows: + + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE() + (+++) __HAL_RCC_ETH1TX_CLK_ENABLE() + (+++) __HAL_RCC_ETH1RX_CLK_ENABLE() + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pinout + (##) Configure Ethernet NVIC interrupt (in Interrupt mode) + + (#) Ethernet data reception is asynchronous, so call the following API + to start the listening mode: + (##) HAL_ETH_Start(): + This API starts the MAC and DMA transmission and reception process, + without enabling end of transfer interrupts, in this mode user + has to poll for data reception by calling HAL_ETH_ReadData() + (##) HAL_ETH_Start_IT(): + This API starts the MAC and DMA transmission and reception process, + end of transfer interrupts are enabled in this mode, + HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received + + (#) When data is received user can call the following API to get received data: + (##) HAL_ETH_ReadData(): Read a received packet + + (#) For transmission path, two APIs are available: + (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode + (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode, + HAL_ETH_TxCpltCallback() will be executed when end of transfer occur + + (#) Communication with an external PHY device: + (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY + (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register + + (#) Configure the Ethernet MAC after ETH peripheral initialization + (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef + (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef + + (#) Configure the Ethernet DMA after ETH peripheral initialization + (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef + (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef + + (#) Configure the Ethernet PTP after ETH peripheral initialization + (##) Define HAL_ETH_USE_PTP to use PTP APIs. + (##) HAL_ETH_PTP_GetConfig(): Get PTP actual configuration into ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_SetConfig(): Set PTP configuration based on ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_GetTime(): Get Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_SetTime(): Set Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_AddTimeOffset(): Add Seconds and Nanoseconds offset for the Ethernet PTP registers + (##) HAL_ETH_PTP_InsertTxTimestamp(): Insert Timestamp in transmission + (##) HAL_ETH_PTP_GetTxTimestamp(): Get transmission timestamp + (##) HAL_ETH_PTP_GetRxTimestamp(): Get reception timestamp + + -@- The ARP offload feature is not supported in this driver. + + -@- The PTP offload feature is not supported in this driver. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callbacks RxAllocateCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxPtpCallback(). + + Use function HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + For specific callbacks RxAllocateCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxPtpCallback(). + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ETH_TxCpltCallback(), HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_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_ETH_RegisterCallback() before calling HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_MACCR_MASK 0xFFFB7F7CU +#define ETH_MACECR_MASK 0x3F077FFFU +#define ETH_MACFFR_MASK 0x800007FFU +#define ETH_MACWTR_MASK 0x0000010FU +#define ETH_MACTFCR_MASK 0xFFFF00F2U +#define ETH_MACRFCR_MASK 0x00000003U +#define ETH_MTLTQOMR_MASK 0x00000072U +#define ETH_MTLRQOMR_MASK 0x0000007BU + +#define ETH_DMAMR_MASK 0x00007802U +#define ETH_DMASBMR_MASK 0x0000D001U +#define ETH_DMACCR_MASK 0x00013FFFU +#define ETH_DMACTCR_MASK 0x003F1010U +#define ETH_DMACRCR_MASK 0x803F0000U +#define ETH_MACPMTCSR_MASK (ETH_MACPMTCSR_PD | ETH_MACPMTCSR_WFE | \ + ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU) + +/* Timeout values */ +#define ETH_SWRESET_TIMEOUT 500U +#define ETH_MDIO_BUS_TIMEOUT 1000U + +#define ETH_DMARXDESC_ERRORS_MASK ((uint32_t)(ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | \ + ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT |\ + ETH_DMARXDESC_LC | ETH_DMARXDESC_CE |\ + ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE)) + +#define ETH_MAC_US_TICK 1000000U + +#define ETH_MACTSCR_MASK 0x0087FF2FU + +#define ETH_PTPTSHR_VALUE 0xFFFFFFFFU +#define ETH_PTPTSLR_VALUE 0xBB9ACA00U + +/* Ethernet MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/* Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY 0x00000001U + +/* ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFF20810FU + +/* ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/* ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (uint32_t)(ETH_MAC_BASE + 0x40U) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (uint32_t)(ETH_MAC_BASE + 0x44U) /* ETHERNET MAC address low offset */ + +/* ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Macros ETH Private Macros + * @{ + */ +/* Helper macros for TX descriptor handling */ +#define INCR_TX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\ + } while (0) + +/* Helper macros for RX descriptor handling */ +#define INCR_RX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\ + } while (0) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth); +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth); +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth); +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode); +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth); +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth); +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the ETH peripheral: + + (+) User must Implement HAL_ETH_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO and NVIC ). + + (+) Call the function HAL_ETH_Init() to configure the selected device with + the selected configuration: + (++) MAC address + (++) Media interface (MII or RMII) + (++) Rx DMA Descriptors Tab + (++) Tx DMA Descriptors Tab + (++) Length of Rx Buffers + + (+) Call the function HAL_ETH_DeInit() to restore the default configuration + of the selected ETH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the Ethernet peripheral registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tickstart; + + if (heth == NULL) + { + return HAL_ERROR; + } + if (heth->gState == HAL_ETH_STATE_RESET) + { + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + ETH_InitCallbacksToDefault(heth); + + if (heth->MspInitCallback == NULL) + { + heth->MspInitCallback = HAL_ETH_MspInit; + } + + /* Init the low level hardware */ + heth->MspInitCallback(heth); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + } + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Select MII or RMII Mode*/ + SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL); + SYSCFG->PMC |= (uint32_t)heth->Init.MediaInterface; + /* Dummy read to sync SYSCFG with ETH */ + (void)SYSCFG->PMC; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + SET_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + } + + + /*------------------ MAC, MTL and DMA default Configuration ----------------*/ + ETH_MACDMAConfig(heth); + + + /*------------------ DMA Tx Descriptors Configuration ----------------------*/ + ETH_DMATxDescListInit(heth); + + /*------------------ DMA Rx Descriptors Configuration ----------------------*/ + ETH_DMARxDescListInit(heth); + + /*--------------------- ETHERNET MAC Address Configuration ------------------*/ + ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr); + + heth->ErrorCode = HAL_ETH_ERROR_NONE; + heth->gState = HAL_ETH_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the ETH peripheral. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + if (heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* DeInit the low level hardware */ + heth->MspDeInitCallback(heth); +#else + + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + + /* Set ETH HAL state to Disabled */ + heth->gState = HAL_ETH_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = pCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = pCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callabck is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = HAL_ETH_PMTCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief ETH Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the ETH + data transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables Ethernet MAC and DMA reception and transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* Set nombre of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + heth->gState = HAL_ETH_STATE_STARTED; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* save IT mode to ETH Handle */ + heth->RxDescList.ItMode = 1U; + /* Disable MMC Interrupts */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM); + + /* Disable Rx MMC Interrupts */ + SET_BIT(heth->Instance->MMCRIMR, ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | \ + ETH_MMCRIMR_RFCEM); + + /* Disable Tx MMC Interrupts */ + SET_BIT(heth->Instance->MMCTIMR, ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | \ + ETH_MMCTIMR_TGFSCM); + + /* Set nombre of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Enable ETH DMA interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + heth->gState = HAL_ETH_STATE_STARTED; + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t descindex; + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Clear IOC bit to all Rx descriptors */ + for (descindex = 0; descindex < (uint32_t)ETH_RX_DESC_CNT; descindex++) + { + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex]; + SET_BIT(dmarxdesc->DESC1, ETH_DMARXDESC_DIC); + } + + heth->RxDescList.ItMode = 0U; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in polling mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @param Timeout: timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout) +{ + uint32_t tickstart; + ETH_DMADescTypeDef *dmatxdesc; + + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE) + { + /* Set the ETH error code */ + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc]; + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMATPDR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + tickstart = HAL_GetTick(); + + /* Wait for data to be transmitted or timeout occurred */ + while ((dmatxdesc->DESC0 & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + if ((heth->Instance->DMASR & ETH_DMASR_FBES) != (uint32_t)RESET) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + heth->DMAErrorCode = heth->Instance->DMASR; + /* Return function status */ + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT; + /* Clear TX descriptor so that we can proceed */ + dmatxdesc->DESC0 = (ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + return HAL_ERROR; + } + } + } + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in interrupt mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig) +{ + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Save the packet pointer to release. */ + heth->TxDescList.CurrentPacketAddress = (uint32_t *)pTxConfig->pData; + + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE) + { + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + (heth->Instance)->DMASR = ETH_DMASR_TBUS; + /* Resume DMA transmission*/ + (heth->Instance)->DMATPDR = 0U; + } + + return HAL_OK; + + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Read a received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pAppBuff: Pointer to an application buffer to receive the packet. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff) +{ + uint32_t descidx; + ETH_DMADescTypeDef *dmarxdesc; + uint32_t desccnt = 0U; + uint32_t desccntmax; + uint32_t bufflength; + uint8_t rxdataready = 0U; + + + if (pAppBuff == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState != HAL_ETH_STATE_STARTED) + { + return HAL_ERROR; + } + + descidx = heth->RxDescList.RxDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccntmax = ETH_RX_DESC_CNT - heth->RxDescList.RxBuildDescCnt; + + /* Check if descriptor is not owned by DMA */ + while ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (desccnt < desccntmax) + && (rxdataready == 0U)) + { + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Get timestamp high */ + heth->RxDescList.TimeStamp.TimeStampHigh = dmarxdesc->DESC6; + /* Get timestamp low */ + heth->RxDescList.TimeStamp.TimeStampLow = dmarxdesc->DESC7; + } + if ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) || (heth->RxDescList.pRxStart != NULL)) + { + /* Check first descriptor */ + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) + { + heth->RxDescList.RxDescCnt = 0; + heth->RxDescList.RxDataLength = 0; + } + + /* Check if last descriptor */ + bufflength = heth->Init.RxBuffLen; + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + bufflength = ((dmarxdesc->DESC0 & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U; + + /* Save Last descriptor index */ + heth->RxDescList.pRxLastRxDesc = dmarxdesc->DESC0; + + /* Packet ready */ + rxdataready = 1; + } + + /* Link data */ + WRITE_REG(dmarxdesc->BackupAddr0, dmarxdesc->DESC2); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Link callback*/ + heth->rxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, bufflength); +#else + /* Link callback */ + HAL_ETH_RxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, (uint16_t) bufflength); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->RxDescList.RxDescCnt++; + heth->RxDescList.RxDataLength += bufflength; + + /* Clear buffer pointer */ + dmarxdesc->BackupAddr0 = 0; + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccnt++; + } + + heth->RxDescList.RxBuildDescCnt += desccnt; + if ((heth->RxDescList.RxBuildDescCnt) != 0U) + { + /* Update Descriptors */ + ETH_UpdateDescriptor(heth); + } + + heth->RxDescList.RxDescIdx = descidx; + + if (rxdataready == 1U) + { + /* Return received packet */ + *pAppBuff = heth->RxDescList.pRxStart; + /* Reset first element */ + heth->RxDescList.pRxStart = NULL; + + return HAL_OK; + } + + /* Packet not ready */ + return HAL_ERROR; +} + +/** + * @brief This function gives back Rx Desc of the last received Packet + * to the DMA, so ETH DMA will be able to use these descriptors + * to receive next Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth) +{ + uint32_t descidx; + uint32_t desccount; + ETH_DMADescTypeDef *dmarxdesc; + uint8_t *buff = NULL; + uint8_t allocStatus = 1U; + + descidx = heth->RxDescList.RxBuildDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount = heth->RxDescList.RxBuildDescCnt; + + while ((desccount > 0U) && (allocStatus != 0U)) + { + /* Check if a buffer's attached the descriptor */ + if (READ_REG(dmarxdesc->BackupAddr0) == 0U) + { + /* Get a new buffer. */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Allocate callback*/ + heth->rxAllocateCallback(&buff); +#else + /* Allocate callback */ + HAL_ETH_RxAllocateCallback(&buff); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + if (buff == NULL) + { + allocStatus = 0U; + } + else + { + WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)buff); + WRITE_REG(dmarxdesc->DESC2, (uint32_t)buff); + } + } + + if (allocStatus != 0U) + { + if (heth->RxDescList.ItMode == 0U) + { + WRITE_REG(dmarxdesc->DESC1, ETH_DMARXDESC_DIC | ETH_RX_BUF_SIZE | ETH_DMARXDESC_RCH); + } + else + { + WRITE_REG(dmarxdesc->DESC1, ETH_RX_BUF_SIZE | ETH_DMARXDESC_RCH); + } + + /* Before transferring the ownership to DMA, make sure that the RX descriptors bits writing + is fully performed. + The __DMB() instruction is added to avoid any potential compiler optimization that + may lead to abnormal behavior. */ + __DMB(); + + SET_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN); + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount--; + } + } + + if (heth->RxDescList.RxBuildDescCnt != desccount) + { + /* Set the Tail pointer address */ + WRITE_REG(heth->Instance->DMARPDR, 0); + + heth->RxDescList.RxBuildDescIdx = descidx; + heth->RxDescList.RxBuildDescCnt = desccount; + } +} + +/** + * @brief Register the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxAllocateCallback: pointer to function to alloc buffer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback) +{ + if (rxAllocateCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to allocate buffer */ + heth->rxAllocateCallback = rxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Rx Allocate callback. + * @param buff: pointer to allocated buffer + * @retval None + */ +__weak void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxAllocateCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Link callback. + * @param pStart: pointer to packet start + * @param pStart: pointer to packet end + * @param buff: pointer to received data + * @param Length: received data length + * @retval None + */ +__weak void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(pStart); + UNUSED(pEnd); + UNUSED(buff); + UNUSED(Length); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxLinkCallback could be implemented in the user file + */ +} + +/** + * @brief Set the Rx link data function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxLinkCallback: pointer to function to link data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback) +{ + if (rxLinkCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to link data */ + heth->rxLinkCallback = rxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx link callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Get the error state of the last received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pErrorCode: pointer to uint32_t to hold the error code + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode) +{ + /* Get error bits. */ + *pErrorCode = READ_BIT(heth->RxDescList.pRxLastRxDesc, ETH_DMARXDESC_ERRORS_MASK); + + return HAL_OK; +} + +/** + * @brief Set the Tx free function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txFreeCallback: pointer to function to release the packet + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback) +{ + if (txFreeCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to free transmmitted packet */ + heth->txFreeCallback = txFreeCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx free callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; + + return HAL_OK; +} + +/** + * @brief Tx Free callback. + * @param buff: pointer to buffer to free + * @retval None + */ +__weak void HAL_ETH_TxFreeCallback(uint32_t *buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxFreeCallback could be implemented in the user file + */ +} + +/** + * @brief Release transmitted Tx packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t numOfBuf = dmatxdesclist->BuffersInUse; + uint32_t idx = dmatxdesclist->releaseIndex; + uint8_t pktTxStatus = 1U; + uint8_t pktInUse; +#ifdef HAL_ETH_USE_PTP + ETH_TimeStampTypeDef *timestamp = &heth->TxTimestamp; +#endif /* HAL_ETH_USE_PTP */ + + /* Loop through buffers in use. */ + while ((numOfBuf != 0U) && (pktTxStatus != 0U)) + { + pktInUse = 1U; + numOfBuf--; + /* If no packet, just examine the next packet. */ + if (dmatxdesclist->PacketAddress[idx] == NULL) + { + /* No packet in use, skip to next. */ + idx = (idx + 1U) & (ETH_TX_DESC_CNT - 1U); + pktInUse = 0U; + } + + if (pktInUse != 0U) + { + /* Determine if the packet has been transmitted. */ + if ((heth->Init.TxDesc[idx].DESC0 & ETH_DMATXDESC_OWN) == 0U) + { +#ifdef HAL_ETH_USE_PTP + /* Get timestamp low */ + timestamp->TimeStampLow = heth->Init.TxDesc[idx].DESC6; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->Init.TxDesc[idx].DESC7; +#endif /* HAL_ETH_USE_PTP */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered callbacks*/ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + heth->txPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + heth->txFreeCallback(dmatxdesclist->PacketAddress[idx]); +#else + /* Call callbacks */ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + HAL_ETH_TxPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + HAL_ETH_TxFreeCallback(dmatxdesclist->PacketAddress[idx]); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the entry in the in-use array. */ + dmatxdesclist->PacketAddress[idx] = NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + idx = (idx + 1U) & (ETH_TX_DESC_CNT - 1U); + dmatxdesclist->BuffersInUse = numOfBuf; + dmatxdesclist->releaseIndex = idx; + } + else + { + /* Get out of the loop! */ + pktTxStatus = 0U; + } + } + } + return HAL_OK; +} + +#ifdef HAL_ETH_USE_PTP +/** + * @brief Set the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + uint32_t tmpTSCR; + ETH_TimeTypeDef time; + + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + + tmpTSCR = ptpconfig->Timestamp | + ((uint32_t)ptpconfig->TimestampUpdate << ETH_PTPTSCR_TSFCU_Pos) | + ((uint32_t)ptpconfig->TimestampAll << ETH_PTPTSCR_TSSARFE_Pos) | + ((uint32_t)ptpconfig->TimestampRolloverMode << ETH_PTPTSCR_TSSSR_Pos) | + ((uint32_t)ptpconfig->TimestampV2 << ETH_PTPTSCR_TSPTPPSV2E_Pos) | + ((uint32_t)ptpconfig->TimestampEthernet << ETH_PTPTSCR_TSSPTPOEFE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv6 << ETH_PTPTSCR_TSSIPV6FE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv4 << ETH_PTPTSCR_TSSIPV4FE_Pos) | + ((uint32_t)ptpconfig->TimestampEvent << ETH_PTPTSCR_TSSEME_Pos) | + ((uint32_t)ptpconfig->TimestampMaster << ETH_PTPTSCR_TSSMRME_Pos) | + ((uint32_t)ptpconfig->TimestampFilter << ETH_PTPTSCR_TSPFFMAE_Pos) | + ((uint32_t)ptpconfig->TimestampClockType << ETH_PTPTSCR_TSCNT_Pos); + + /* Write to MACTSCR */ + MODIFY_REG(heth->Instance->PTPTSCR, ETH_MACTSCR_MASK, tmpTSCR); + + /* Enable Timestamp */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + WRITE_REG(heth->Instance->PTPSSIR, ptpconfig->TimestampSubsecondInc); + WRITE_REG(heth->Instance->PTPTSAR, ptpconfig->TimestampAddend); + + /* Enable Timestamp */ + if (ptpconfig->TimestampAddendUpdate == ENABLE) + { + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSARU); + while ((heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU) != 0) {} + } + + /* Enable Update mode */ + if (ptpconfig->TimestampUpdateMode == ENABLE) + { + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSFCU); + } + + /* Initialize Time */ + time.Seconds = 0; + time.NanoSeconds = 0; + HAL_ETH_PTP_SetTime(heth, &time); + + /* Ptp Init */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSTI); + + /* Set PTP Configuration done */ + heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURATED; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Get the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + ptpconfig->Timestamp = READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + ptpconfig->TimestampUpdate = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSFCU) >> ETH_PTPTSCR_TSFCU_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampAll = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSARFE) >> ETH_PTPTSCR_TSSARFE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampRolloverMode = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSSR) >> ETH_PTPTSCR_TSSSR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampV2 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPTPPSV2E) >> ETH_PTPTSCR_TSPTPPSV2E_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEthernet = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSPTPOEFE) >> ETH_PTPTSCR_TSSPTPOEFE_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampIPv6 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV6FE) >> ETH_PTPTSCR_TSSIPV6FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv4 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV4FE) >> ETH_PTPTSCR_TSSIPV4FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEvent = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSEME) >> ETH_PTPTSCR_TSSEME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampMaster = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSMRME) >> ETH_PTPTSCR_TSSMRME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampFilter = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPFFMAE) >> ETH_PTPTSCR_TSPFFMAE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampClockType = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSCNT) >> ETH_PTPTSCR_TSCNT_Pos) > 0U) ? ENABLE : DISABLE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param heth: pointer to a ETH_TimeTypeDef structure that contains + * time to set + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Set Seconds */ + heth->Instance->PTPTSHUR = time->Seconds; + + /* Set NanoSeconds */ + heth->Instance->PTPTSLUR = time->NanoSeconds; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param heth: pointer to a ETH_TimeTypeDef structure that contains + * time to get + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get Seconds */ + time->Seconds = heth->Instance->PTPTSHR; + + /* Get NanoSeconds */ + time->NanoSeconds = heth->Instance->PTPTSLR; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Update time for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timeupdate: pointer to a ETH_TIMEUPDATETypeDef structure that contains + * the time update information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + if (ptpoffsettype == HAL_ETH_PTP_NEGATIVE_UPDATE) + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = ETH_PTPTSHR_VALUE - timeoffset->Seconds + 1U; + + if (READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSSR) == ETH_PTPTSCR_TSSSR) + { + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = ETH_PTPTSLR_VALUE - timeoffset->NanoSeconds; + } + else + { + heth->Instance->PTPTSLUR = ETH_PTPTSHR_VALUE - timeoffset->NanoSeconds + 1U; + } + } + else + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = timeoffset->Seconds; + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = timeoffset->NanoSeconds; + } + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Insert Timestamp in transmission. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txtimestampconf: Enable or Disable timestamp in transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Enable Time Stamp transmission */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TTSE); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get transmission timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * transmission timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t idx = dmatxdesclist->releaseIndex; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[idx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = dmatxdesc->DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = dmatxdesc->DESC1; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get receive timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * receive timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->RxDescList.TimeStamp.TimeStampLow; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->RxDescList.TimeStamp.TimeStampHigh; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Register the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txPtpCallback: Function to handle Ptp transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback) +{ + if (txPtpCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + /* Set Function to handle Tx Ptp */ + heth->txPtpCallback = txPtpCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txPtpCallback = HAL_ETH_TxPtpCallback; + + return HAL_OK; +} + +/** + * @brief Tx Ptp callback. + * @param buff: pointer to application buffer + * @retval None + */ +__weak void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxPtpCallback could be implemented in the user file + */ +} +#endif /* HAL_ETH_USE_PTP */ + +/** + * @brief This function handles ETH interrupt request. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + /* Packet received */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_RS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_RIE)) + { + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_RS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } + + /* Packet transmitted */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_TS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_TIE)) + { + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_TS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Transmit complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } + + + /* ETH DMA Error */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_AIS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_AISE)) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + + /* if fatal bus error occurred */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_FBES)) + { + /* Get DMA error code */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS)); + + /* Disable all interrupts */ + __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMAIER_NISE | ETH_DMAIER_AISE); + + /* Set HAL state to ERROR */ + heth->gState = HAL_ETH_STATE_ERROR; + } + else + { + /* Get DMA error status */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + + /* Clear the interrupt summary flag */ + __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + } +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet DMA Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + } + } + + + /* ETH PMT IT */ + if (__HAL_ETH_MAC_GET_IT(heth, ETH_MAC_PMT_IT)) + { + /* Get MAC Wake-up source and clear the status register pending bit */ + heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPMTCSR, (ETH_MACPMTCSR_WFR | ETH_MACPMTCSR_MPR)); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered PMT callback*/ + heth->PMTCallback(heth); +#else + /* Ethernet PMT callback */ + HAL_ETH_PMTCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACWakeUpEvent = (uint32_t)(0x0U); + } + + + /* check ETH WAKEUP exti flag */ + if (__HAL_ETH_WAKEUP_EXTI_GET_FLAG(ETH_WAKEUP_EXTI_LINE) != (uint32_t)RESET) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet Power Management module IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_PMTCallback could be implemented in the user file + */ +} + + +/** + * @brief ETH WAKEUP interrupt callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_WakeUpCallback could be implemented in the user file + */ +} + +/** + * @brief Read a PHY register + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param pRegValue: parameter to hold read value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII address register value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_READ_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + /* Get MACMIIDR value */ + *pRegValue = (uint16_t)(heth->Instance->MACMIIDR); + + return HAL_OK; +} + + +/** + * @brief Writes to a PHY register. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param RegValue: the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII register address value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Give the value to the MII data register */ + heth->Instance->MACMIIDR = (uint16_t)RegValue; + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_WRITE_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief ETH control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the ETH + peripheral. + +@endverbatim + * @{ + */ +/** + * @brief Get the configuration of the MAC and MTL subsystems. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold + * the configuration of the MAC. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + /* Get MAC parameters */ + macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL); + macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_RD) >> 9) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CSD) >> 16) > 0U) + ? ENABLE : DISABLE; + macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ROD) >> 13) == 0U) ? ENABLE : DISABLE; + macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE; + macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM); + macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES); + macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >> 22) == 0U) ? ENABLE : DISABLE; + macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >> 23) == 0U) ? ENABLE : DISABLE; + macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_APCS) >> 7) > 0U) ? ENABLE : DISABLE; + macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IFG); + macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPCO) >> 10U) > 0U) ? ENABLE : DISABLE; + + + macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_TFCE) >> 1) > 0U) ? ENABLE : DISABLE; + macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_ZQPD) >> 7) == 0U) ? ENABLE : DISABLE; + macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PLT); + macconf->PauseTime = (READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PT) >> 16); + macconf->ReceiveFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_RFCE) >> 2U) > 0U) ? ENABLE : DISABLE; + macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_UPFD) >> 3U) > 0U) + ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Get the configuration of the DMA. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMABMR, + (ETH_DMAARBITRATION_RXPRIORTX | ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1)); + dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_AAB) >> 25U) > 0U) ? ENABLE : DISABLE; + dmaconf->BurstMode = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_FB | ETH_DMABMR_MB); + dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_RDP); + dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_PBL); + dmaconf->EnhancedDescriptorFormat = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_EDE) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->DescriptorSkipLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_DSL) >> 2; + + dmaconf->DropTCPIPChecksumErrorFrame = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_DTCEFD) >> 26) > 0U) ? DISABLE : ENABLE; + dmaconf->ReceiveStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RSF) >> 25) > 0U) ? ENABLE : DISABLE; + dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FTF) >> 20) > 0U) ? DISABLE : ENABLE; + dmaconf->TransmitStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TSF) >> 21) > 0U) ? ENABLE : DISABLE; + dmaconf->TransmitThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TTC); + dmaconf->ForwardErrorFrames = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FEF) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->ForwardUndersizedGoodFrames = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_FUGF) >> 6) > 0U) ? ENABLE : DISABLE; + dmaconf->ReceiveThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RTC); + dmaconf->SecondFrameOperate = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_OSF) >> 2) > 0U) ? ENABLE : DISABLE; + return HAL_OK; +} + +/** + * @brief Set the MAC configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains + * the configuration of the MAC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetMACConfig(heth, macconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Set the ETH DMA configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetDMAConfig(heth, dmaconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configures the Clock range of ETH MDIO interface. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth) +{ + uint32_t hclk; + uint32_t tmpreg; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg = (heth->Instance)->MACMIIAR; + /* Clear CSR Clock Range CR[2:0] bits */ + tmpreg &= ETH_MACMIIAR_CR_MASK; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if ((hclk >= 20000000U) && (hclk < 35000000U)) + { + /* CSR Clock Range between 20-35 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div16; + } + else if ((hclk >= 35000000U) && (hclk < 60000000U)) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div26; + } + else if ((hclk >= 60000000U) && (hclk < 100000000U)) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42; + } + else if ((hclk >= 100000000U) && (hclk < 150000000U)) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div62; + } + else /* ((hclk >= 150000000)&&(hclk <= 183000000))*/ + { + /* CSR Clock Range between 150-183 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div102; + } + + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */ + (heth->Instance)->MACMIIAR = (uint32_t)tmpreg; +} + +/** + * @brief Set the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + uint32_t filterconfig; + uint32_t tmpreg1; + + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode | + ((uint32_t)pFilterConfig->HashUnicast << 1) | + ((uint32_t)pFilterConfig->HashMulticast << 2) | + ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) | + ((uint32_t)pFilterConfig->PassAllMulticast << 4) | + ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) | + ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) | + ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) | + ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) | + ((uint32_t)pFilterConfig->ReceiveAllMode << 31) | + pFilterConfig->ControlPacketsFilter); + + MODIFY_REG(heth->Instance->MACFFR, ETH_MACFFR_MASK, filterconfig); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFFR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFFR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Get the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PM)) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HU) >> 1) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HM) >> 2) > 0U) ? ENABLE : DISABLE; + pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE; + pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PAM) >> 4) > 0U) ? ENABLE : DISABLE; + pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_BFD) >> 5) == 0U) ? ENABLE : DISABLE; + pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PCF); + pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE; + pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HPF) >> 10) > 0U) + ? ENABLE : DISABLE; + pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_RA) >> 31) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the source MAC Address to be matched. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param AddrNbr: The MAC address to configure + * This parameter must be a value of the following: + * ETH_MAC_ADDRESS1 + * ETH_MAC_ADDRESS2 + * ETH_MAC_ADDRESS3 + * @param pMACAddr: Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(ETH_HandleTypeDef *heth, uint32_t AddrNbr, uint8_t *pMACAddr) +{ + uint32_t macaddrlr; + uint32_t macaddrhr; + + if (pMACAddr == NULL) + { + return HAL_ERROR; + } + + /* Get mac addr high reg offset */ + macaddrhr = ((uint32_t) &(heth->Instance->MACA0HR) + AddrNbr); + /* Get mac addr low reg offset */ + macaddrlr = ((uint32_t) &(heth->Instance->MACA0LR) + AddrNbr); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) | + ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= (ETH_MACA1HR_AE | ETH_MACA1HR_SA); + + return HAL_OK; +} + +/** + * @brief Set the ETH Hash Table Value. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pHashTable: pointer to a table of two 32 bit values, that contains + * the 64 bits of the hash table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable) +{ + uint32_t tmpreg1; + if (pHashTable == NULL) + { + return HAL_ERROR; + } + + heth->Instance->MACHTHR = pHashTable[0]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTHR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTHR = tmpreg1; + + heth->Instance->MACHTLR = pHashTable[1]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTLR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTLR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Identifier for Rx packets + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ComparisonBits: 12 or 16 bit comparison mode + must be a value of @ref ETH_VLAN_Tag_Comparison + * @param VLANIdentifier: VLAN Identifier value + * @retval None + */ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier) +{ + uint32_t tmpreg1; + MODIFY_REG(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTI, VLANIdentifier); + if (ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT) + { + CLEAR_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + else + { + SET_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACVLANTR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACVLANTR = tmpreg1; +} + +/** + * @brief Enters the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure + * that contains the Power Down configuration + * @retval None. + */ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, ETH_PowerDownConfigTypeDef *pPowerDownConfig) +{ + uint32_t powerdownconfig; + + powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << ETH_MACPMTCSR_MPE_Pos) | + ((uint32_t)pPowerDownConfig->WakeUpPacket << ETH_MACPMTCSR_WFE_Pos) | + ((uint32_t)pPowerDownConfig->GlobalUnicast << ETH_MACPMTCSR_GU_Pos) | + ETH_MACPMTCSR_PD); + + MODIFY_REG(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_MASK, powerdownconfig); +} + +/** + * @brief Exits from the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + /* clear wake up sources */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFE | ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + + if (READ_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD) != 0U) + { + /* Exit power down mode */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + } + + /* Disable PMT interrupt */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_PMTIM); +} + +/** + * @brief Set the WakeUp filter. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilter: pointer to filter registers values + * @param Count: number of filter registers, must be from 1 to 8. + * @retval None. + */ +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count) +{ + uint32_t regindex; + + if (pFilter == NULL) + { + return HAL_ERROR; + } + + /* Reset Filter Pointer */ + SET_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFFRPR); + + /* Wake up packet filter config */ + for (regindex = 0; regindex < Count; regindex++) + { + /* Write filter regs */ + WRITE_REG(heth->Instance->MACRWUFFR, pFilter[regindex]); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief ETH State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + ETH communication process, return Peripheral Errors occurred during communication + process + + +@endverbatim + * @{ + */ + +/** + * @brief Returns the ETH state. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth) +{ + return heth->gState; +} + +/** + * @brief Returns the ETH error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH Error Code + */ +uint32_t HAL_ETH_GetError(ETH_HandleTypeDef *heth) +{ + return heth->ErrorCode; +} + +/** + * @brief Returns the ETH DMA error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH DMA Error Code + */ +uint32_t HAL_ETH_GetDMAError(ETH_HandleTypeDef *heth) +{ + return heth->DMAErrorCode; +} + +/** + * @brief Returns the ETH MAC error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC Error Code + */ +uint32_t HAL_ETH_GetMACError(ETH_HandleTypeDef *heth) +{ + return heth->MACErrorCode; +} + +/** + * @brief Returns the ETH MAC WakeUp event source + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event source + */ +uint32_t HAL_ETH_GetMACWakeUpSource(ETH_HandleTypeDef *heth) +{ + return heth->MACWakeUpEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions ETH Private Functions + * @{ + */ + +/** + * @brief Clears the ETHERNET transmit FIFO. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg = 0; + + /* Set the Flush Transmit FIFO bit */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg; +} + +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + uint32_t tmpreg1; + + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpreg1 &= ETH_MACCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 23U) | + ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 22U) | + (uint32_t)macconf->InterPacketGapVal | + ((uint32_t)macconf->CarrierSenseDuringTransmit << 16U) | + macconf->Speed | + ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 13U) | + ((uint32_t)macconf->LoopbackMode << 12U) | + macconf->DuplexMode | + ((uint32_t)macconf->ChecksumOffload << 10U) | + ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 9U) | + ((uint32_t)macconf->AutomaticPadCRCStrip << 7U) | + macconf->BackOffLimit | + ((uint32_t)macconf->DeferralCheck << 4U)); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /*----------------------- ETHERNET MACFCR Configuration --------------------*/ + + /* Get the ETHERNET MACFCR value */ + tmpreg1 = (heth->Instance)->MACFCR; + /* Clear xx bits */ + tmpreg1 &= ETH_MACFCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) | + ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U) << 7U) | + macconf->PauseLowThreshold | + ((uint32_t)((macconf->UnicastPausePacketDetect == ENABLE) ? 1U : 0U) << 3U) | + ((uint32_t)((macconf->ReceiveFlowControl == ENABLE) ? 1U : 0U) << 2U) | + ((uint32_t)((macconf->TransmitFlowControl == ENABLE) ? 1U : 0U) << 1U)); + + /* Write to ETHERNET MACFCR */ + (heth->Instance)->MACFCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFCR = tmpreg1; +} + +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + uint32_t tmpreg1; + + /*----------------------- ETHERNET DMAOMR Configuration --------------------*/ + /* Get the ETHERNET DMAOMR value */ + tmpreg1 = (heth->Instance)->DMAOMR; + /* Clear xx bits */ + tmpreg1 &= ETH_DMAOMR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)((dmaconf->DropTCPIPChecksumErrorFrame == DISABLE) ? 1U : 0U) << 26U) | + ((uint32_t)dmaconf->ReceiveStoreForward << 25U) | + ((uint32_t)((dmaconf->FlushRxPacket == DISABLE) ? 1U : 0U) << 20U) | + ((uint32_t)dmaconf->TransmitStoreForward << 21U) | + dmaconf->TransmitThresholdControl | + ((uint32_t)dmaconf->ForwardErrorFrames << 7U) | + ((uint32_t)dmaconf->ForwardUndersizedGoodFrames << 6U) | + dmaconf->ReceiveThresholdControl | + ((uint32_t)dmaconf->SecondFrameOperate << 2U)); + + /* Write to ETHERNET DMAOMR */ + (heth->Instance)->DMAOMR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; + + /*----------------------- ETHERNET DMABMR Configuration --------------------*/ + (heth->Instance)->DMABMR = (uint32_t)(((uint32_t)dmaconf->AddressAlignedBeats << 25U) | + dmaconf->BurstMode | + dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or + Rx it is applied for the other */ + dmaconf->TxDMABurstLength | + ((uint32_t)dmaconf->EnhancedDescriptorFormat << 7U) | + (dmaconf->DescriptorSkipLength << 2U) | + dmaconf->DMAArbitration | + ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMABMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMABMR = tmpreg1; +} + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth) +{ + ETH_MACConfigTypeDef macDefaultConf; + ETH_DMAConfigTypeDef dmaDefaultConf; + + /*--------------- ETHERNET MAC registers default Configuration --------------*/ + macDefaultConf.Watchdog = ENABLE; + macDefaultConf.Jabber = ENABLE; + macDefaultConf.InterPacketGapVal = ETH_INTERFRAMEGAP_96BIT; + macDefaultConf.CarrierSenseDuringTransmit = DISABLE; + macDefaultConf.ReceiveOwn = ENABLE; + macDefaultConf.LoopbackMode = DISABLE; + macDefaultConf.ChecksumOffload = ENABLE; + macDefaultConf.RetryTransmission = DISABLE; + macDefaultConf.AutomaticPadCRCStrip = DISABLE; + macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10; + macDefaultConf.DeferralCheck = DISABLE; + macDefaultConf.PauseTime = 0x0U; + macDefaultConf.ZeroQuantaPause = DISABLE; + macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + macDefaultConf.ReceiveFlowControl = DISABLE; + macDefaultConf.TransmitFlowControl = DISABLE; + macDefaultConf.Speed = ETH_SPEED_100M; + macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE; + macDefaultConf.UnicastPausePacketDetect = DISABLE; + + /* MAC default configuration */ + ETH_SetMACConfig(heth, &macDefaultConf); + + /*--------------- ETHERNET DMA registers default Configuration --------------*/ + dmaDefaultConf.DropTCPIPChecksumErrorFrame = ENABLE; + dmaDefaultConf.ReceiveStoreForward = ENABLE; + dmaDefaultConf.FlushRxPacket = ENABLE; + dmaDefaultConf.TransmitStoreForward = ENABLE; + dmaDefaultConf.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.ForwardErrorFrames = DISABLE; + dmaDefaultConf.ForwardUndersizedGoodFrames = DISABLE; + dmaDefaultConf.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.SecondFrameOperate = ENABLE; + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.EnhancedDescriptorFormat = ENABLE; + dmaDefaultConf.DescriptorSkipLength = 0x0U; + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; + + /* DMA default configuration */ + ETH_SetDMAConfig(heth, &dmaDefaultConf); +} + +/** + * @brief Configures the selected MAC address. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param MacAddr The MAC address to configure + * This parameter can be one of the following values: + * @arg ETH_MAC_Address0: MAC Address0 + * @arg ETH_MAC_Address1: MAC Address1 + * @arg ETH_MAC_Address2: MAC Address2 + * @arg ETH_MAC_Address3: MAC Address3 + * @param Addr Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg1; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + + /* Calculate the selected MAC address high register */ + tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U]; + /* Load the selected MAC address high register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1; + /* Calculate the selected MAC address low register */ + tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U]; + + /* Load the selected MAC address low register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1; +} + +/** + * @brief Initializes the DMA Tx descriptors. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmatxdesc; + uint32_t i; + + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++) + { + dmatxdesc = heth->Init.TxDesc + i; + + WRITE_REG(dmatxdesc->DESC0, 0x0); + WRITE_REG(dmatxdesc->DESC1, 0x0); + WRITE_REG(dmatxdesc->DESC2, 0x0); + WRITE_REG(dmatxdesc->DESC3, 0x0); + + WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc); + + /* Set Second Address Chained bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TCH); + + if (i < ((uint32_t)ETH_TX_DESC_CNT - 1U)) + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc + i + 1U)); + } + else + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc)); + } + + /* Set the DMA Tx descriptors checksum insertion */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL); + } + + heth->TxDescList.CurTxDesc = 0; + + /* Set Transmit Descriptor List Address */ + WRITE_REG(heth->Instance->DMATDLAR, (uint32_t) heth->Init.TxDesc); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t i; + + for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++) + { + dmarxdesc = heth->Init.RxDesc + i; + + WRITE_REG(dmarxdesc->DESC0, 0x0); + WRITE_REG(dmarxdesc->DESC1, 0x0); + WRITE_REG(dmarxdesc->DESC2, 0x0); + WRITE_REG(dmarxdesc->DESC3, 0x0); + WRITE_REG(dmarxdesc->BackupAddr0, 0x0); + WRITE_REG(dmarxdesc->BackupAddr1, 0x0); + + /* Set Own bit of the Rx descriptor Status */ + dmarxdesc->DESC0 = ETH_DMARXDESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + dmarxdesc->DESC1 = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE; + + /* Enable Ethernet DMA Rx Descriptor interrupt */ + dmarxdesc->DESC1 &= ~ETH_DMARXDESC_DIC; + + /* Set Rx descritors addresses */ + WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc); + + if (i < ((uint32_t)ETH_RX_DESC_CNT - 1U)) + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc + i + 1U)); + } + else + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc)); + } + } + + WRITE_REG(heth->RxDescList.RxDescIdx, 0); + WRITE_REG(heth->RxDescList.RxDescCnt, 0); + WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0); + WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0); + WRITE_REG(heth->RxDescList.ItMode, 0); + + /* Set Receive Descriptor List Address */ + WRITE_REG(heth->Instance->DMARDLAR, (uint32_t) heth->Init.RxDesc); +} + +/** + * @brief Prepare Tx DMA descriptor before transmission. + * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Tx packet configuration + * @param ItMode: Enable or disable Tx EOT interrept + * @retval Status + */ +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + uint32_t firstdescidx = dmatxdesclist->CurTxDesc; + uint32_t idx; + uint32_t descnbr = 0; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer; + uint32_t bd_count = 0; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + return HAL_ETH_ERROR_BUSY; + } + + + descnbr += 1U; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_DMATXDESC_CIC, pTxConfig->ChecksumCtrl); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_CRC_PAD_DISABLE, pTxConfig->CRCPadCtrl); + } + + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U) + { + /* Set Vlan Type */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_VF); + } + + /* Mark it as First Descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* set OWN bit of FIRST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + + /* only if the packet is split into more than one descriptors > 1 */ + while (txbuffer->next != NULL) + { + /* Clear the LD bit of previous descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* Clear the FD bit of new Descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + descidx = firstdescidx; + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* clear previous desc own bit */ + for (idx = 0; idx < descnbr; idx ++) + { + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + } + + return HAL_ETH_ERROR_BUSY; + } + + descnbr += 1U; + + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + bd_count += 1U; + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set Own bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + } + + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + + /* Mark it as LAST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + /* Save the current packet address to expose it to the application */ + dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress; + + dmatxdesclist->CurTxDesc = descidx; + + /* disable the interrupt */ + __disable_irq(); + + dmatxdesclist->BuffersInUse += bd_count + 1U; + + /* Enable interrupts back */ + __enable_irq(); + + + /* Return function status */ + return HAL_ETH_ERROR_NONE; +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->ErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak ErrorCallback */ + heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */ + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; /* Legacy weak RxLinkCallback */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; /* Legacy weak TxFreeCallback */ +#ifdef HAL_ETH_USE_PTP + heth->txPtpCallback = HAL_ETH_TxPtpCallback; /* Legacy weak TxPtpCallback */ +#endif /* HAL_ETH_USE_PTP */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; /* Legacy weak RxAllocateCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ + +/** + * @} + */ + diff --git a/libs/hal/stm32f4xx_hal_exti.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c similarity index 98% rename from libs/hal/stm32f4xx_hal_exti.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c index 04b5215..0804555 100644 --- a/libs/hal/stm32f4xx_hal_exti.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_exti.c @@ -300,8 +300,8 @@ HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigT { assert_param(IS_EXTI_GPIO_PIN(linepos)); - regval = (SYSCFG->EXTICR[linepos >> 2u] << 16u ); - pExtiConfig->GPIOSel = ((regval << (SYSCFG_EXTICR1_EXTI1_Pos * (3uL - (linepos & 0x03u)))) >> 28u); + regval = SYSCFG->EXTICR[linepos >> 2u]; + pExtiConfig->GPIOSel = (regval >> (SYSCFG_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & SYSCFG_EXTICR1_EXTI0; } } diff --git a/libs/hal/stm32f4xx_hal_flash.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c similarity index 100% rename from libs/hal/stm32f4xx_hal_flash.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash.c diff --git a/libs/hal/stm32f4xx_hal_flash_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_flash_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex.c diff --git a/libs/hal/stm32f4xx_hal_flash_ramfunc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c similarity index 100% rename from libs/hal/stm32f4xx_hal_flash_ramfunc.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ramfunc.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c new file mode 100644 index 0000000..4b42546 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c.c @@ -0,0 +1,7322 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpi2c.c + * @author MCD Application Team + * @brief FMPI2C HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Inter Integrated Circuit (FMPI2C) peripheral: + * + Initialization and de-initialization functions + * + IO operation 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 FMPI2C HAL driver can be used as follows: + + (#) Declare a FMPI2C_HandleTypeDef handle structure, for example: + FMPI2C_HandleTypeDef hfmpi2c; + + (#)Initialize the FMPI2C low level resources by implementing the HAL_FMPI2C_MspInit() API: + (##) Enable the FMPI2Cx interface clock + (##) FMPI2C pins configuration + (+++) Enable the clock for the FMPI2C GPIOs + (+++) Configure FMPI2C pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the FMPI2Cx interrupt priority + (+++) Enable the NVIC FMPI2C IRQ Channel + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for + the transmit or receive stream + (+++) Enable the DMAx interface clock using + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx stream + (+++) Associate the initialized DMA handle to the hfmpi2c DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on + the DMA Tx or Rx stream + + (#) Configure the Communication Clock Timing, Own Address1, Master Addressing mode, Dual Addressing mode, + Own Address2, Own Address2 Mask, General call and Nostretch mode in the hfmpi2c Init structure. + + (#) Initialize the FMPI2C registers by calling the HAL_FMPI2C_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_FMPI2C_MspInit(&hfmpi2c) API. + + (#) To check if target device is ready for communication, use the function HAL_FMPI2C_IsDeviceReady() + + (#) For FMPI2C IO and IO MEM operations, three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Transmit in master mode an amount of data in blocking mode using HAL_FMPI2C_Master_Transmit() + (+) Receive in master mode an amount of data in blocking mode using HAL_FMPI2C_Master_Receive() + (+) Transmit in slave mode an amount of data in blocking mode using HAL_FMPI2C_Slave_Transmit() + (+) Receive in slave mode an amount of data in blocking mode using HAL_FMPI2C_Slave_Receive() + + *** Polling mode IO MEM operation *** + ===================================== + [..] + (+) Write an amount of data in blocking mode to a specific memory address using HAL_FMPI2C_Mem_Write() + (+) Read an amount of data in blocking mode from a specific memory address using HAL_FMPI2C_Mem_Read() + + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode using HAL_FMPI2C_Master_Transmit_IT() + (+) At transmission end of transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode using HAL_FMPI2C_Master_Receive_IT() + (+) At reception end of transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_FMPI2C_Slave_Transmit_IT() + (+) At transmission end of transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode using HAL_FMPI2C_Slave_Receive_IT() + (+) At reception end of transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback() + (+) Abort a master FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT() + (+) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback() + (+) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + + *** Interrupt mode or DMA mode IO sequential operation *** + ========================================================== + [..] + (@) These interfaces allow to manage a sequential transfer with a repeated start condition + when a direction change during transfer + [..] + (+) A specific option field manage the different steps of a sequential transfer + (+) Option field values are defined through FMPI2C_XFEROPTIONS and are listed below: + (++) FMPI2C_FIRST_AND_LAST_FRAME: No sequential usage, functional is same as associated interfaces in + no sequential mode + (++) FMPI2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition + (++) FMPI2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with + start condition, address and data to transfer without a final stop condition, + an then permit a call the same master sequential interface several times + (like HAL_FMPI2C_Master_Seq_Transmit_IT() then HAL_FMPI2C_Master_Seq_Transmit_IT() + or HAL_FMPI2C_Master_Seq_Transmit_DMA() then HAL_FMPI2C_Master_Seq_Transmit_DMA()) + (++) FMPI2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to + transfer + if no direction change and without a final stop condition in both cases + (++) FMPI2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to + transfer + if no direction change and with a final stop condition in both cases + (++) FMPI2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition + after several call of the same master sequential interface several times + (link with option FMPI2C_FIRST_AND_NEXT_FRAME). + Usage can, transfer several bytes one by one using + HAL_FMPI2C_Master_Seq_Transmit_IT + or HAL_FMPI2C_Master_Seq_Receive_IT + or HAL_FMPI2C_Master_Seq_Transmit_DMA + or HAL_FMPI2C_Master_Seq_Receive_DMA + with option FMPI2C_FIRST_AND_NEXT_FRAME then FMPI2C_NEXT_FRAME. + Then usage of this option FMPI2C_LAST_FRAME_NO_STOP at the last Transmit or + Receive sequence permit to call the opposite interface Receive or Transmit + without stopping the communication and so generate a restart condition. + (++) FMPI2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after + each call of the same master sequential + interface. + Usage can, transfer several bytes one by one with a restart with slave address between + each bytes using + HAL_FMPI2C_Master_Seq_Transmit_IT + or HAL_FMPI2C_Master_Seq_Receive_IT + or HAL_FMPI2C_Master_Seq_Transmit_DMA + or HAL_FMPI2C_Master_Seq_Receive_DMA + with option FMPI2C_FIRST_FRAME then FMPI2C_OTHER_FRAME. + Then usage of this option FMPI2C_OTHER_AND_LAST_FRAME at the last frame to help automatic + generation of STOP condition. + + (+) Different sequential FMPI2C interfaces are listed below: + (++) Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode using + HAL_FMPI2C_Master_Seq_Transmit_IT() or using HAL_FMPI2C_Master_Seq_Transmit_DMA() + (+++) At transmission end of current frame transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and + users can add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback() + (++) Sequential receive in master FMPI2C mode an amount of data in non-blocking mode using + HAL_FMPI2C_Master_Seq_Receive_IT() or using HAL_FMPI2C_Master_Seq_Receive_DMA() + (+++) At reception end of current frame transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback() + (++) Abort a master IT or DMA FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT() + (+++) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback() + (++) Enable/disable the Address listen mode in slave FMPI2C mode using HAL_FMPI2C_EnableListen_IT() + HAL_FMPI2C_DisableListen_IT() + (+++) When address slave FMPI2C match, HAL_FMPI2C_AddrCallback() is executed and users can + add their own code to check the Address Match Code and the transmission direction request by master + (Write/Read). + (+++) At Listen mode end HAL_FMPI2C_ListenCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ListenCpltCallback() + (++) Sequential transmit in slave FMPI2C mode an amount of data in non-blocking mode using + HAL_FMPI2C_Slave_Seq_Transmit_IT() or using HAL_FMPI2C_Slave_Seq_Transmit_DMA() + (+++) At transmission end of current frame transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and + users can add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback() + (++) Sequential receive in slave FMPI2C mode an amount of data in non-blocking mode using + HAL_FMPI2C_Slave_Seq_Receive_IT() or using HAL_FMPI2C_Slave_Seq_Receive_DMA() + (+++) At reception end of current frame transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback() + (++) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback() + (++) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** Interrupt mode IO MEM operation *** + ======================================= + [..] + (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using + HAL_FMPI2C_Mem_Write_IT() + (+) At Memory end of write transfer, HAL_FMPI2C_MemTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using + HAL_FMPI2C_Mem_Read_IT() + (+) At Memory end of read transfer, HAL_FMPI2C_MemRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback() + + *** DMA mode IO operation *** + ============================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using + HAL_FMPI2C_Master_Transmit_DMA() + (+) At transmission end of transfer, HAL_FMPI2C_MasterTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode (DMA) using + HAL_FMPI2C_Master_Receive_DMA() + (+) At reception end of transfer, HAL_FMPI2C_MasterRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using + HAL_FMPI2C_Slave_Transmit_DMA() + (+) At transmission end of transfer, HAL_FMPI2C_SlaveTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using + HAL_FMPI2C_Slave_Receive_DMA() + (+) At reception end of transfer, HAL_FMPI2C_SlaveRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback() + (+) Abort a master FMPI2C process communication with Interrupt using HAL_FMPI2C_Master_Abort_IT() + (+) End of abort process, HAL_FMPI2C_AbortCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_AbortCpltCallback() + (+) Discard a slave FMPI2C process communication using __HAL_FMPI2C_GENERATE_NACK() macro. + This action will inform Master to generate a Stop condition to discard the communication. + + *** DMA mode IO MEM operation *** + ================================= + [..] + (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using + HAL_FMPI2C_Mem_Write_DMA() + (+) At Memory end of write transfer, HAL_FMPI2C_MemTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using + HAL_FMPI2C_Mem_Read_DMA() + (+) At Memory end of read transfer, HAL_FMPI2C_MemRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_FMPI2C_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPI2C_ErrorCallback() + + + *** FMPI2C HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in FMPI2C HAL driver. + + (+) __HAL_FMPI2C_ENABLE: Enable the FMPI2C peripheral + (+) __HAL_FMPI2C_DISABLE: Disable the FMPI2C peripheral + (+) __HAL_FMPI2C_GENERATE_NACK: Generate a Non-Acknowledge FMPI2C peripheral in Slave mode + (+) __HAL_FMPI2C_GET_FLAG: Check whether the specified FMPI2C flag is set or not + (+) __HAL_FMPI2C_CLEAR_FLAG: Clear the specified FMPI2C pending flag + (+) __HAL_FMPI2C_ENABLE_IT: Enable the specified FMPI2C interrupt + (+) __HAL_FMPI2C_DISABLE_IT: Disable the specified FMPI2C interrupt + + *** Callback registration *** + ============================================= + [..] + The compilation flag USE_HAL_FMPI2C_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_FMPI2C_RegisterCallback() or HAL_FMPI2C_RegisterAddrCallback() + to register an interrupt callback. + [..] + Function HAL_FMPI2C_RegisterCallback() allows to register following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) MemTxCpltCallback : callback for Memory transmission end of transfer. + (+) MemRxCpltCallback : callback for Memory reception end of transfer. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + For specific callback AddrCallback use dedicated register callbacks : HAL_FMPI2C_RegisterAddrCallback(). + [..] + Use function HAL_FMPI2C_UnRegisterCallback to reset a callback to the default + weak function. + HAL_FMPI2C_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) MemTxCpltCallback : callback for Memory transmission end of transfer. + (+) MemRxCpltCallback : callback for Memory reception end of transfer. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + [..] + For callback AddrCallback use dedicated register callbacks : HAL_FMPI2C_UnRegisterAddrCallback(). + [..] + By default, after the HAL_FMPI2C_Init() and when the state is HAL_FMPI2C_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_FMPI2C_MasterTxCpltCallback(), HAL_FMPI2C_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_FMPI2C_Init()/ HAL_FMPI2C_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_FMPI2C_Init()/ HAL_FMPI2C_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + [..] + Callbacks can be registered/unregistered in HAL_FMPI2C_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_FMPI2C_STATE_READY or HAL_FMPI2C_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_FMPI2C_RegisterCallback() before calling HAL_FMPI2C_DeInit() + or HAL_FMPI2C_Init() function. + [..] + When the compilation flag USE_HAL_FMPI2C_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + [..] + (@) You can refer to the FMPI2C HAL driver header file for more useful macros + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup FMPI2C FMPI2C + * @brief FMPI2C HAL module driver + * @{ + */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED +#if defined(FMPI2C_CR1_PE) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup FMPI2C_Private_Define FMPI2C Private Define + * @{ + */ +#define TIMING_CLEAR_MASK (0xF0FFFFFFU) /*!< FMPI2C TIMING clear register Mask */ +#define FMPI2C_TIMEOUT_ADDR (10000U) /*!< 10 s */ +#define FMPI2C_TIMEOUT_BUSY (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_DIR (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_RXNE (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_STOPF (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_TC (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_TCR (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_TXIS (25U) /*!< 25 ms */ +#define FMPI2C_TIMEOUT_FLAG (25U) /*!< 25 ms */ + +#define MAX_NBYTE_SIZE 255U +#define SLAVE_ADDR_SHIFT 7U +#define SLAVE_ADDR_MSK 0x06U + +/* Private define for @ref PreviousState usage */ +#define FMPI2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_FMPI2C_STATE_BUSY_TX | \ + (uint32_t)HAL_FMPI2C_STATE_BUSY_RX) & \ + (uint32_t)(~((uint32_t)HAL_FMPI2C_STATE_READY)))) +/*!< Mask State define, keep only RX and TX bits */ +#define FMPI2C_STATE_NONE ((uint32_t)(HAL_FMPI2C_MODE_NONE)) +/*!< Default Value */ +#define FMPI2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_MASTER)) +/*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define FMPI2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_MASTER)) +/*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define FMPI2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_SLAVE)) +/*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define FMPI2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_SLAVE)) +/*!< Slave Busy RX, combinaison of State LSB and Mode enum */ +#define FMPI2C_STATE_MEM_BUSY_TX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_TX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_MEM)) +/*!< Memory Busy TX, combinaison of State LSB and Mode enum */ +#define FMPI2C_STATE_MEM_BUSY_RX ((uint32_t)(((uint32_t)HAL_FMPI2C_STATE_BUSY_RX & FMPI2C_STATE_MSK) | \ + (uint32_t)HAL_FMPI2C_MODE_MEM)) +/*!< Memory Busy RX, combinaison of State LSB and Mode enum */ + + +/* Private define to centralize the enable/disable of Interrupts */ +#define FMPI2C_XFER_TX_IT (uint16_t)(0x0001U) /*!< Bit field can be combinated with + @ref FMPI2C_XFER_LISTEN_IT */ +#define FMPI2C_XFER_RX_IT (uint16_t)(0x0002U) /*!< Bit field can be combinated with + @ref FMPI2C_XFER_LISTEN_IT */ +#define FMPI2C_XFER_LISTEN_IT (uint16_t)(0x8000U) /*!< Bit field can be combinated with @ref FMPI2C_XFER_TX_IT + and @ref FMPI2C_XFER_RX_IT */ + +#define FMPI2C_XFER_ERROR_IT (uint16_t)(0x0010U) /*!< Bit definition to manage addition of global Error + and NACK treatment */ +#define FMPI2C_XFER_CPLT_IT (uint16_t)(0x0020U) /*!< Bit definition to manage only STOP evenement */ +#define FMPI2C_XFER_RELOAD_IT (uint16_t)(0x0040U) /*!< Bit definition to manage only Reload of NBYTE */ + +/* Private define Sequential Transfer Options default/reset value */ +#define FMPI2C_NO_OPTION_FRAME (0xFFFF0000U) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Macro to get remaining data to transfer on DMA side */ +#define FMPI2C_GET_DMA_REMAIN_DATA(__HANDLE__) __HAL_DMA_GET_COUNTER(__HANDLE__) + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup FMPI2C_Private_Functions FMPI2C Private Functions + * @{ + */ +/* Private functions to handle DMA transfer */ +static void FMPI2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma); +static void FMPI2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma); +static void FMPI2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma); +static void FMPI2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma); +static void FMPI2C_DMAError(DMA_HandleTypeDef *hdma); +static void FMPI2C_DMAAbort(DMA_HandleTypeDef *hdma); + +/* Private functions to handle IT transfer */ +static void FMPI2C_ITAddrCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags); +static void FMPI2C_ITMasterSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c); +static void FMPI2C_ITSlaveSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c); +static void FMPI2C_ITMasterCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags); +static void FMPI2C_ITSlaveCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags); +static void FMPI2C_ITListenCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags); +static void FMPI2C_ITError(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ErrorCode); + +/* Private functions to handle IT transfer */ +static HAL_StatusTypeDef FMPI2C_RequestMemoryWrite(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, + uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, + uint32_t Tickstart); +static HAL_StatusTypeDef FMPI2C_RequestMemoryRead(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, + uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, + uint32_t Tickstart); + +/* Private functions for FMPI2C transfer IRQ handler */ +static HAL_StatusTypeDef FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); +static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); +static HAL_StatusTypeDef FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); +static HAL_StatusTypeDef FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); +static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); +static HAL_StatusTypeDef FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources); + +/* Private functions to handle flags during polling transfer */ +static HAL_StatusTypeDef FMPI2C_WaitOnFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Flag, FlagStatus Status, + uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef FMPI2C_WaitOnTXISFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart); +static HAL_StatusTypeDef FMPI2C_WaitOnRXNEFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart); +static HAL_StatusTypeDef FMPI2C_WaitOnSTOPFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart); +static HAL_StatusTypeDef FMPI2C_IsErrorOccurred(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart); + +/* Private functions to centralize the enable/disable of Interrupts */ +static void FMPI2C_Enable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest); +static void FMPI2C_Disable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest); + +/* Private function to treat different error callback */ +static void FMPI2C_TreatErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c); + +/* Private function to flush TXDR register */ +static void FMPI2C_Flush_TXDR(FMPI2C_HandleTypeDef *hfmpi2c); + +/* Private function to handle start, restart or stop a transfer */ +static void FMPI2C_TransferConfig(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, + uint32_t Request); + +/* Private function to Convert Specific options */ +static void FMPI2C_ConvertOtherXferOptions(FMPI2C_HandleTypeDef *hfmpi2c); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup FMPI2C_Exported_Functions FMPI2C Exported Functions + * @{ + */ + +/** @defgroup FMPI2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the FMPI2Cx peripheral: + + (+) User must Implement HAL_FMPI2C_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_FMPI2C_Init() to configure the selected device with + the selected configuration: + (++) Clock Timing + (++) Own Address 1 + (++) Addressing mode (Master, Slave) + (++) Dual Addressing mode + (++) Own Address 2 + (++) Own Address 2 Mask + (++) General call mode + (++) Nostretch mode + + (+) Call the function HAL_FMPI2C_DeInit() to restore the default configuration + of the selected FMPI2Cx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FMPI2C according to the specified parameters + * in the FMPI2C_InitTypeDef and initialize the associated handle. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Init(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Check the FMPI2C handle allocation */ + if (hfmpi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance)); + assert_param(IS_FMPI2C_OWN_ADDRESS1(hfmpi2c->Init.OwnAddress1)); + assert_param(IS_FMPI2C_ADDRESSING_MODE(hfmpi2c->Init.AddressingMode)); + assert_param(IS_FMPI2C_DUAL_ADDRESS(hfmpi2c->Init.DualAddressMode)); + assert_param(IS_FMPI2C_OWN_ADDRESS2(hfmpi2c->Init.OwnAddress2)); + assert_param(IS_FMPI2C_OWN_ADDRESS2_MASK(hfmpi2c->Init.OwnAddress2Masks)); + assert_param(IS_FMPI2C_GENERAL_CALL(hfmpi2c->Init.GeneralCallMode)); + assert_param(IS_FMPI2C_NO_STRETCH(hfmpi2c->Init.NoStretchMode)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hfmpi2c->Lock = HAL_UNLOCKED; + +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + /* Init the FMPI2C Callback settings */ + hfmpi2c->MasterTxCpltCallback = HAL_FMPI2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + hfmpi2c->MasterRxCpltCallback = HAL_FMPI2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + hfmpi2c->SlaveTxCpltCallback = HAL_FMPI2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + hfmpi2c->SlaveRxCpltCallback = HAL_FMPI2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + hfmpi2c->ListenCpltCallback = HAL_FMPI2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + hfmpi2c->MemTxCpltCallback = HAL_FMPI2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */ + hfmpi2c->MemRxCpltCallback = HAL_FMPI2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */ + hfmpi2c->ErrorCallback = HAL_FMPI2C_ErrorCallback; /* Legacy weak ErrorCallback */ + hfmpi2c->AbortCpltCallback = HAL_FMPI2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + hfmpi2c->AddrCallback = HAL_FMPI2C_AddrCallback; /* Legacy weak AddrCallback */ + + if (hfmpi2c->MspInitCallback == NULL) + { + hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + hfmpi2c->MspInitCallback(hfmpi2c); +#else + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_FMPI2C_MspInit(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY; + + /* Disable the selected FMPI2C peripheral */ + __HAL_FMPI2C_DISABLE(hfmpi2c); + + /*---------------------------- FMPI2Cx TIMINGR Configuration ------------------*/ + /* Configure FMPI2Cx: Frequency range */ + hfmpi2c->Instance->TIMINGR = hfmpi2c->Init.Timing & TIMING_CLEAR_MASK; + + /*---------------------------- FMPI2Cx OAR1 Configuration ---------------------*/ + /* Disable Own Address1 before set the Own Address1 configuration */ + hfmpi2c->Instance->OAR1 &= ~FMPI2C_OAR1_OA1EN; + + /* Configure FMPI2Cx: Own Address1 and ack own address1 mode */ + if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_7BIT) + { + hfmpi2c->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | hfmpi2c->Init.OwnAddress1); + } + else /* FMPI2C_ADDRESSINGMODE_10BIT */ + { + hfmpi2c->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | FMPI2C_OAR1_OA1MODE | hfmpi2c->Init.OwnAddress1); + } + + /*---------------------------- FMPI2Cx CR2 Configuration ----------------------*/ + /* Configure FMPI2Cx: Addressing Master mode */ + if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT) + { + hfmpi2c->Instance->CR2 = (FMPI2C_CR2_ADD10); + } + /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process */ + hfmpi2c->Instance->CR2 |= (FMPI2C_CR2_AUTOEND | FMPI2C_CR2_NACK); + + /*---------------------------- FMPI2Cx OAR2 Configuration ---------------------*/ + /* Disable Own Address2 before set the Own Address2 configuration */ + hfmpi2c->Instance->OAR2 &= ~FMPI2C_DUALADDRESS_ENABLE; + + /* Configure FMPI2Cx: Dual mode and Own Address2 */ + hfmpi2c->Instance->OAR2 = (hfmpi2c->Init.DualAddressMode | hfmpi2c->Init.OwnAddress2 | \ + (hfmpi2c->Init.OwnAddress2Masks << 8)); + + /*---------------------------- FMPI2Cx CR1 Configuration ----------------------*/ + /* Configure FMPI2Cx: Generalcall and NoStretch mode */ + hfmpi2c->Instance->CR1 = (hfmpi2c->Init.GeneralCallMode | hfmpi2c->Init.NoStretchMode); + + /* Enable the selected FMPI2C peripheral */ + __HAL_FMPI2C_ENABLE(hfmpi2c); + + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + return HAL_OK; +} + +/** + * @brief DeInitialize the FMPI2C peripheral. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_DeInit(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Check the FMPI2C handle allocation */ + if (hfmpi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance)); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY; + + /* Disable the FMPI2C Peripheral Clock */ + __HAL_FMPI2C_DISABLE(hfmpi2c); + +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + if (hfmpi2c->MspDeInitCallback == NULL) + { + hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + hfmpi2c->MspDeInitCallback(hfmpi2c); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_FMPI2C_MspDeInit(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + hfmpi2c->State = HAL_FMPI2C_STATE_RESET; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Initialize the FMPI2C MSP. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MspInit(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the FMPI2C MSP. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MspDeInit(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User FMPI2C Callback + * To be used instead of the weak predefined callback + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID + * @arg @ref HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_ERROR_CB_ID Error callback ID + * @arg @ref HAL_FMPI2C_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_FMPI2C_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_FMPI2C_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_RegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID, + pFMPI2C_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + if (HAL_FMPI2C_STATE_READY == hfmpi2c->State) + { + switch (CallbackID) + { + case HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID : + hfmpi2c->MasterTxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID : + hfmpi2c->MasterRxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID : + hfmpi2c->SlaveTxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID : + hfmpi2c->SlaveRxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_LISTEN_COMPLETE_CB_ID : + hfmpi2c->ListenCpltCallback = pCallback; + break; + + case HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID : + hfmpi2c->MemTxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID : + hfmpi2c->MemRxCpltCallback = pCallback; + break; + + case HAL_FMPI2C_ERROR_CB_ID : + hfmpi2c->ErrorCallback = pCallback; + break; + + case HAL_FMPI2C_ABORT_CB_ID : + hfmpi2c->AbortCpltCallback = pCallback; + break; + + case HAL_FMPI2C_MSPINIT_CB_ID : + hfmpi2c->MspInitCallback = pCallback; + break; + + case HAL_FMPI2C_MSPDEINIT_CB_ID : + hfmpi2c->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_FMPI2C_STATE_RESET == hfmpi2c->State) + { + switch (CallbackID) + { + case HAL_FMPI2C_MSPINIT_CB_ID : + hfmpi2c->MspInitCallback = pCallback; + break; + + case HAL_FMPI2C_MSPDEINIT_CB_ID : + hfmpi2c->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpi2c); + return status; +} + +/** + * @brief Unregister an FMPI2C Callback + * FMPI2C callback is redirected to the weak predefined callback + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * This parameter can be one of the following values: + * @arg @ref HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID + * @arg @ref HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID + * @arg @ref HAL_FMPI2C_ERROR_CB_ID Error callback ID + * @arg @ref HAL_FMPI2C_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_FMPI2C_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_FMPI2C_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_UnRegisterCallback(FMPI2C_HandleTypeDef *hfmpi2c, HAL_FMPI2C_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + if (HAL_FMPI2C_STATE_READY == hfmpi2c->State) + { + switch (CallbackID) + { + case HAL_FMPI2C_MASTER_TX_COMPLETE_CB_ID : + hfmpi2c->MasterTxCpltCallback = HAL_FMPI2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + break; + + case HAL_FMPI2C_MASTER_RX_COMPLETE_CB_ID : + hfmpi2c->MasterRxCpltCallback = HAL_FMPI2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + break; + + case HAL_FMPI2C_SLAVE_TX_COMPLETE_CB_ID : + hfmpi2c->SlaveTxCpltCallback = HAL_FMPI2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + break; + + case HAL_FMPI2C_SLAVE_RX_COMPLETE_CB_ID : + hfmpi2c->SlaveRxCpltCallback = HAL_FMPI2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + break; + + case HAL_FMPI2C_LISTEN_COMPLETE_CB_ID : + hfmpi2c->ListenCpltCallback = HAL_FMPI2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + break; + + case HAL_FMPI2C_MEM_TX_COMPLETE_CB_ID : + hfmpi2c->MemTxCpltCallback = HAL_FMPI2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */ + break; + + case HAL_FMPI2C_MEM_RX_COMPLETE_CB_ID : + hfmpi2c->MemRxCpltCallback = HAL_FMPI2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */ + break; + + case HAL_FMPI2C_ERROR_CB_ID : + hfmpi2c->ErrorCallback = HAL_FMPI2C_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_FMPI2C_ABORT_CB_ID : + hfmpi2c->AbortCpltCallback = HAL_FMPI2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_FMPI2C_MSPINIT_CB_ID : + hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_FMPI2C_MSPDEINIT_CB_ID : + hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_FMPI2C_STATE_RESET == hfmpi2c->State) + { + switch (CallbackID) + { + case HAL_FMPI2C_MSPINIT_CB_ID : + hfmpi2c->MspInitCallback = HAL_FMPI2C_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_FMPI2C_MSPDEINIT_CB_ID : + hfmpi2c->MspDeInitCallback = HAL_FMPI2C_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpi2c); + return status; +} + +/** + * @brief Register the Slave Address Match FMPI2C Callback + * To be used instead of the weak HAL_FMPI2C_AddrCallback() predefined callback + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pCallback pointer to the Address Match Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_RegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, pFMPI2C_AddrCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + if (HAL_FMPI2C_STATE_READY == hfmpi2c->State) + { + hfmpi2c->AddrCallback = pCallback; + } + else + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpi2c); + return status; +} + +/** + * @brief UnRegister the Slave Address Match FMPI2C Callback + * Info Ready FMPI2C Callback is redirected to the weak HAL_FMPI2C_AddrCallback() predefined callback + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_UnRegisterAddrCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + if (HAL_FMPI2C_STATE_READY == hfmpi2c->State) + { + hfmpi2c->AddrCallback = HAL_FMPI2C_AddrCallback; /* Legacy weak AddrCallback */ + } + else + { + /* Update the error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpi2c); + return status; +} + +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup FMPI2C_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the FMPI2C data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated FMPI2C IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_FMPI2C_Master_Transmit() + (++) HAL_FMPI2C_Master_Receive() + (++) HAL_FMPI2C_Slave_Transmit() + (++) HAL_FMPI2C_Slave_Receive() + (++) HAL_FMPI2C_Mem_Write() + (++) HAL_FMPI2C_Mem_Read() + (++) HAL_FMPI2C_IsDeviceReady() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_FMPI2C_Master_Transmit_IT() + (++) HAL_FMPI2C_Master_Receive_IT() + (++) HAL_FMPI2C_Slave_Transmit_IT() + (++) HAL_FMPI2C_Slave_Receive_IT() + (++) HAL_FMPI2C_Mem_Write_IT() + (++) HAL_FMPI2C_Mem_Read_IT() + (++) HAL_FMPI2C_Master_Seq_Transmit_IT() + (++) HAL_FMPI2C_Master_Seq_Receive_IT() + (++) HAL_FMPI2C_Slave_Seq_Transmit_IT() + (++) HAL_FMPI2C_Slave_Seq_Receive_IT() + (++) HAL_FMPI2C_EnableListen_IT() + (++) HAL_FMPI2C_DisableListen_IT() + (++) HAL_FMPI2C_Master_Abort_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_FMPI2C_Master_Transmit_DMA() + (++) HAL_FMPI2C_Master_Receive_DMA() + (++) HAL_FMPI2C_Slave_Transmit_DMA() + (++) HAL_FMPI2C_Slave_Receive_DMA() + (++) HAL_FMPI2C_Mem_Write_DMA() + (++) HAL_FMPI2C_Mem_Read_DMA() + (++) HAL_FMPI2C_Master_Seq_Transmit_DMA() + (++) HAL_FMPI2C_Master_Seq_Receive_DMA() + (++) HAL_FMPI2C_Slave_Seq_Transmit_DMA() + (++) HAL_FMPI2C_Slave_Seq_Receive_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_FMPI2C_MasterTxCpltCallback() + (++) HAL_FMPI2C_MasterRxCpltCallback() + (++) HAL_FMPI2C_SlaveTxCpltCallback() + (++) HAL_FMPI2C_SlaveRxCpltCallback() + (++) HAL_FMPI2C_MemTxCpltCallback() + (++) HAL_FMPI2C_MemRxCpltCallback() + (++) HAL_FMPI2C_AddrCallback() + (++) HAL_FMPI2C_ListenCpltCallback() + (++) HAL_FMPI2C_ErrorCallback() + (++) HAL_FMPI2C_AbortCpltCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + uint32_t xfermode; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferISR = NULL; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = FMPI2C_AUTOEND_MODE; + } + + if (hfmpi2c->XferSize > 0U) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U), xfermode, + FMPI2C_GENERATE_START_WRITE); + } + else + { + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, + FMPI2C_GENERATE_START_WRITE); + } + + while (hfmpi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + /* Wait until TCR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives in master mode an amount of data in blocking mode. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferISR = NULL; + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_GENERATE_START_READ); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_GENERATE_START_READ); + } + + while (hfmpi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (FMPI2C_WaitOnRXNEFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + /* Wait until TCR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_NO_STARTSTOP); + } + } + } + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmits in slave mode an amount of data in blocking mode. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t Timeout) +{ + uint32_t tickstart; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + + /* If 10bit addressing mode is selected */ + if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT) + { + /* Wait until ADDR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + } + + /* Wait until DIR flag is set Transmitter mode */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_DIR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + while (hfmpi2c->XferCount > 0U) + { + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + } + + /* Wait until AF flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* Clear AF flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Wait until STOP flag is set */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + return HAL_ERROR; + } + + /* Clear STOP flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in blocking mode + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t Timeout) +{ + uint32_t tickstart; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferISR = NULL; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Wait until ADDR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + + /* Wait until DIR flag is reset Receiver mode */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_DIR, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + while (hfmpi2c->XferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (FMPI2C_WaitOnRXNEFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + /* Store Last receive data if any */ + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == SET) + { + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + + return HAL_ERROR; + } + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + + /* Wait until STOP flag is set */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Clear STOP flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Wait until BUSY flag is reset */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + return HAL_ERROR; + } + + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size) +{ + uint32_t xfermode; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = FMPI2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */ + if (hfmpi2c->XferSize > 0U) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U), xfermode, + FMPI2C_GENERATE_START_WRITE); + } + else + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, + FMPI2C_GENERATE_START_WRITE); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size) +{ + uint32_t xfermode; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = FMPI2C_AUTOEND_MODE; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size) +{ + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT | FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size) +{ + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with DMA + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size) +{ + uint32_t xfermode; + HAL_StatusTypeDef dmaxferstatus; + uint32_t sizetoxfer = 0U; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Master_ISR_DMA; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = FMPI2C_AUTOEND_MODE; + } + + if (hfmpi2c->XferSize > 0U) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + sizetoxfer = hfmpi2c->XferSize; + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + + if (hfmpi2c->XferSize > 0U) + { + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmatx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr, + (uint32_t)&hfmpi2c->Instance->TXDR, hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)(hfmpi2c->XferSize + 1U), + xfermode, FMPI2C_GENERATE_START_WRITE); + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + else + { + /* Update Transfer ISR function pointer */ + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to write and generate START condition */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, FMPI2C_AUTOEND_MODE, + FMPI2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with DMA + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size) +{ + uint32_t xfermode; + HAL_StatusTypeDef dmaxferstatus; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Master_ISR_DMA; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = FMPI2C_AUTOEND_MODE; + } + + if (hfmpi2c->XferSize > 0U) + { + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmarx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address */ + /* Set NBYTES to read and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_GENERATE_START_READ); + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + else + { + /* Update Transfer ISR function pointer */ + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to read and generate START condition */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_DMA; + + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMASlaveTransmitCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmatx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)pData, (uint32_t)&hfmpi2c->Instance->TXDR, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with DMA + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_DMA; + + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMASlaveReceiveCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmarx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in blocking mode to a specific memory address + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (FMPI2C_RequestMemoryWrite(hfmpi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + return HAL_ERROR; + } + + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP); + } + + do + { + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + /* Wait until TCR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_NO_STARTSTOP); + } + } + + } while (hfmpi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in blocking mode from a specific memory address + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_BUSY, SET, FMPI2C_TIMEOUT_BUSY, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferISR = NULL; + + /* Send Slave Address and Memory Address */ + if (FMPI2C_RequestMemoryRead(hfmpi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + return HAL_ERROR; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_GENERATE_START_READ); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_GENERATE_START_READ); + } + + do + { + /* Wait until RXNE flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + /* Wait until TCR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t) hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, + FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_NO_STARTSTOP); + } + } + } while (hfmpi2c->XferCount > 0U); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is reset */ + if (FMPI2C_WaitOnSTOPFlagUntilTimeout(hfmpi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Mem_ISR_IT; + hfmpi2c->Devaddress = DevAddress; + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Prefetch Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + /* If Memory address size is 16Bit */ + else + { + /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Prepare Memaddress buffer for LSB part */ + hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress); + } + /* Send Slave Address and Memory Address */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Mem_ISR_IT; + hfmpi2c->Devaddress = DevAddress; + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Prefetch Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + /* If Memory address size is 16Bit */ + else + { + /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Prepare Memaddress buffer for LSB part */ + hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress); + } + /* Send Slave Address and Memory Address */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, (FMPI2C_XFER_TX_IT | FMPI2C_XFER_RX_IT)); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Write_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Mem_ISR_DMA; + hfmpi2c->Devaddress = DevAddress; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Prefetch Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + /* If Memory address size is 16Bit */ + else + { + /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Prepare Memaddress buffer for LSB part */ + hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress); + } + + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmatx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)pData, (uint32_t)&hfmpi2c->Instance->TXDR, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and Memory Address */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Mem_Read_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint16_t MemAddress, + uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_FMPI2C_MEMADD_SIZE(MemAddSize)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MEM; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferISR = FMPI2C_Mem_ISR_DMA; + hfmpi2c->Devaddress = DevAddress; + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Prefetch Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + /* If Memory address size is 16Bit */ + else + { + /* Prefetch Memory Address (MSB part, LSB will be manage through interrupt) */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Prepare Memaddress buffer for LSB part */ + hfmpi2c->Memaddress = FMPI2C_MEM_ADD_LSB(MemAddress); + } + + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmarx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and Memory Address */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_IsDeviceReady(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint32_t Trials, + uint32_t Timeout) +{ + uint32_t tickstart; + + __IO uint32_t FMPI2C_Trials = 0UL; + + FlagStatus tmp1; + FlagStatus tmp2; + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) == SET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + do + { + /* Generate Start */ + hfmpi2c->Instance->CR2 = FMPI2C_GENERATE_START(hfmpi2c->Init.AddressingMode, DevAddress); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set or a NACK flag is set*/ + tickstart = HAL_GetTick(); + + tmp1 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + tmp2 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + while ((tmp1 == RESET) && (tmp2 == RESET)) + { + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + + tmp1 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + tmp2 = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + } + + /* Check if the NACKF flag has not been set */ + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == RESET) + { + /* Wait until STOPF flag is reset */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Device is ready */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + /* Wait until STOPF flag is reset */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Clear STOP Flag, auto generated with autoend*/ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + } + + /* Check if the maximum allowed number of trials has been reached */ + if (FMPI2C_Trials == Trials) + { + /* Generate Stop */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP; + + /* Wait until STOPF flag is reset */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_STOPF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + } + + /* Increment Trials */ + FMPI2C_Trials++; + } while (FMPI2C_Trials < Trials); + + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode with Interrupt. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode; + uint32_t xferrequest = FMPI2C_GENERATE_START_WRITE; + uint32_t sizetoxfer = 0U; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = hfmpi2c->XferOptions; + } + + if ((hfmpi2c->XferSize > 0U) && ((XferOptions == FMPI2C_FIRST_FRAME) || \ + (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME))) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + sizetoxfer = hfmpi2c->XferSize; + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + + /* If transfer direction not change and there is no request to start another frame, + do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_TX) && \ + (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0)) + { + xferrequest = FMPI2C_NO_STARTSTOP; + } + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPI2C_ConvertOtherXferOptions(hfmpi2c); + + /* Update xfermode accordingly if no reload is necessary */ + if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE) + { + xfermode = hfmpi2c->XferOptions; + } + } + + /* Send Slave Address and set NBYTES to write */ + if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME)) + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest); + } + else + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master FMPI2C mode an amount of data in non-blocking mode with DMA. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode; + uint32_t xferrequest = FMPI2C_GENERATE_START_WRITE; + HAL_StatusTypeDef dmaxferstatus; + uint32_t sizetoxfer = 0U; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Master_ISR_DMA; + + /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = hfmpi2c->XferOptions; + } + + if ((hfmpi2c->XferSize > 0U) && ((XferOptions == FMPI2C_FIRST_FRAME) || \ + (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME))) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + sizetoxfer = hfmpi2c->XferSize; + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + + /* If transfer direction not change and there is no request to start another frame, + do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_TX) && \ + (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0)) + { + xferrequest = FMPI2C_NO_STARTSTOP; + } + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPI2C_ConvertOtherXferOptions(hfmpi2c); + + /* Update xfermode accordingly if no reload is necessary */ + if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE) + { + xfermode = hfmpi2c->XferOptions; + } + } + + if (hfmpi2c->XferSize > 0U) + { + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMAMasterTransmitCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmatx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr, + (uint32_t)&hfmpi2c->Instance->TXDR, hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and set NBYTES to write */ + if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME)) + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest); + } + else + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest); + } + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + else + { + /* Update Transfer ISR function pointer */ + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to write and generate START condition */ + if ((XferOptions == FMPI2C_FIRST_FRAME) || (XferOptions == FMPI2C_FIRST_AND_LAST_FRAME)) + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)sizetoxfer, xfermode, xferrequest); + } + else + { + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master FMPI2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode; + uint32_t xferrequest = FMPI2C_GENERATE_START_READ; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = hfmpi2c->XferOptions; + } + + /* If transfer direction not change and there is no request to start another frame, + do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_RX) && \ + (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0)) + { + xferrequest = FMPI2C_NO_STARTSTOP; + } + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPI2C_ConvertOtherXferOptions(hfmpi2c); + + /* Update xfermode accordingly if no reload is necessary */ + if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE) + { + xfermode = hfmpi2c->XferOptions; + } + } + + /* Send Slave Address and set NBYTES to read */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master FMPI2C mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions) +{ + uint32_t xfermode; + uint32_t xferrequest = FMPI2C_GENERATE_START_READ; + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX; + hfmpi2c->Mode = HAL_FMPI2C_MODE_MASTER; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Master_ISR_DMA; + + /* If hfmpi2c->XferCount > MAX_NBYTE_SIZE, use reload mode */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + xfermode = hfmpi2c->XferOptions; + } + + /* If transfer direction not change and there is no request to start another frame, + do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((hfmpi2c->PreviousState == FMPI2C_STATE_MASTER_BUSY_RX) && \ + (IS_FMPI2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 0)) + { + xferrequest = FMPI2C_NO_STARTSTOP; + } + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPI2C_ConvertOtherXferOptions(hfmpi2c); + + /* Update xfermode accordingly if no reload is necessary */ + if (hfmpi2c->XferCount <= MAX_NBYTE_SIZE) + { + xfermode = hfmpi2c->XferOptions; + } + } + + if (hfmpi2c->XferSize > 0U) + { + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMAMasterReceiveCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmarx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)pData, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and set NBYTES to read */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, xfermode, xferrequest); + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR and NACK interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + else + { + /* Update Transfer ISR function pointer */ + hfmpi2c->XferISR = FMPI2C_Master_ISR_IT; + + /* Send Slave Address */ + /* Set NBYTES to read and generate START condition */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_AUTOEND_MODE, + FMPI2C_GENERATE_START_READ); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + /* possible to enable all of these */ + /* FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | + FMPI2C_IT_ADDRI | FMPI2C_IT_RXI | FMPI2C_IT_TXI */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave/device FMPI2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + FlagStatus tmp; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT); + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN) + { + /* Disable associated Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + /* Abort DMA Xfer if any */ + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx); + } + } + } + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + + tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE) && (tmp != RESET)) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT | FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sequential transmit in slave/device FMPI2C mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Transmit_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + FlagStatus tmp; + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT); + + /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN) + { + /* Disable associated Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN) + { + /* Abort DMA Xfer if any */ + if (hfmpi2c->hdmarx != NULL) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx); + } + } + } + } + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) + { + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + /* Abort DMA Xfer if any */ + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx); + } + } + } + } + else + { + /* Nothing to do */ + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_TX_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_DMA; + + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmatx->XferCpltCallback = FMPI2C_DMASlaveTransmitCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmatx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmatx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)pData, (uint32_t)&hfmpi2c->Instance->TXDR, + hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Reset XferSize */ + hfmpi2c->XferSize = 0; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_RECEIVE) && (tmp != RESET)) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* Enable ERR, STOP, NACK, ADDR interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sequential receive in slave/device FMPI2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + FlagStatus tmp; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT); + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave TX state to RX state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) + { + /* Disable associated Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + /* Abort DMA Xfer if any */ + if (hfmpi2c->hdmatx != NULL) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx); + } + } + } + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + + tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_TRANSMIT) && (tmp != RESET)) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sequential receive in slave/device FMPI2C mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPI2C_XFEROPTIONS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Slave_Seq_Receive_DMA(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + FlagStatus tmp; + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_FMPI2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT); + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* FMPI2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave TX state to RX state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) + { + /* Disable associated Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN) + { + /* Abort DMA Xfer if any */ + if (hfmpi2c->hdmatx != NULL) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx); + } + } + } + } + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN) + { + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + /* Abort DMA Xfer if any */ + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx); + } + } + } + } + else + { + /* Nothing to do */ + } + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY_RX_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_SLAVE; + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + + /* Enable Address Acknowledge */ + hfmpi2c->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpi2c->pBuffPtr = pData; + hfmpi2c->XferCount = Size; + hfmpi2c->XferSize = hfmpi2c->XferCount; + hfmpi2c->XferOptions = XferOptions; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_DMA; + + if (hfmpi2c->hdmarx != NULL) + { + /* Set the FMPI2C DMA transfer complete callback */ + hfmpi2c->hdmarx->XferCpltCallback = FMPI2C_DMASlaveReceiveCplt; + + /* Set the DMA error callback */ + hfmpi2c->hdmarx->XferErrorCallback = FMPI2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hfmpi2c->hdmarx->XferHalfCpltCallback = NULL; + hfmpi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, + (uint32_t)pData, hfmpi2c->XferSize); + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Reset XferSize */ + hfmpi2c->XferSize = 0; + } + else + { + /* Update FMPI2C state */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Update FMPI2C error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + + tmp = __HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + if ((FMPI2C_GET_DIR(hfmpi2c) == FMPI2C_DIRECTION_TRANSMIT) && (tmp != RESET)) + { + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the Master */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Enable DMA Request */ + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_EnableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c) +{ + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + + /* Enable the Address Match interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_DisableListen_IT(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) + { + tmp = (uint32_t)(hfmpi2c->State) & FMPI2C_STATE_MSK; + hfmpi2c->PreviousState = tmp | (uint32_t)(hfmpi2c->Mode); + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + hfmpi2c->XferISR = NULL; + + /* Disable the Address Match interrupt */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master FMPI2C IT or DMA process communication with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2C_Master_Abort_IT(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress) +{ + if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MASTER) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + /* Disable Interrupts and Store Previous state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX; + } + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX; + } + else + { + /* Do nothing */ + } + + /* Set State at HAL_FMPI2C_STATE_ABORT */ + hfmpi2c->State = HAL_FMPI2C_STATE_ABORT; + + /* Set NBYTES to 1 to generate a dummy read on FMPI2C peripheral */ + /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, 1, FMPI2C_AUTOEND_MODE, FMPI2C_GENERATE_STOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Note : The FMPI2C interrupts must be enabled after unlocking current process + to avoid the risk of FMPI2C interrupt handle execution before current + process unlock */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT); + + return HAL_OK; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + return HAL_ERROR; + } +} + +/** + * @} + */ + +/** @defgroup FMPI2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ + +/** + * @brief This function handles FMPI2C event interrupt request. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +void HAL_FMPI2C_EV_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Get current IT Flags and IT sources value */ + uint32_t itflags = READ_REG(hfmpi2c->Instance->ISR); + uint32_t itsources = READ_REG(hfmpi2c->Instance->CR1); + + /* FMPI2C events treatment -------------------------------------*/ + if (hfmpi2c->XferISR != NULL) + { + hfmpi2c->XferISR(hfmpi2c, itflags, itsources); + } +} + +/** + * @brief This function handles FMPI2C error interrupt request. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +void HAL_FMPI2C_ER_IRQHandler(FMPI2C_HandleTypeDef *hfmpi2c) +{ + uint32_t itflags = READ_REG(hfmpi2c->Instance->ISR); + uint32_t itsources = READ_REG(hfmpi2c->Instance->CR1); + uint32_t tmperror; + + /* FMPI2C Bus error interrupt occurred ------------------------------------*/ + if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_BERR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_BERR); + } + + /* FMPI2C Over-Run/Under-Run interrupt occurred ----------------------------------------*/ + if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_OVR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_OVR); + } + + /* FMPI2C Arbitration Loss error interrupt occurred -------------------------------------*/ + if ((FMPI2C_CHECK_FLAG(itflags, FMPI2C_FLAG_ARLO) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(itsources, FMPI2C_IT_ERRI) != RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ARLO); + } + + /* Store current volatile hfmpi2c->ErrorCode, misra rule */ + tmperror = hfmpi2c->ErrorCode; + + /* Call the Error Callback in case of Error detected */ + if ((tmperror & (HAL_FMPI2C_ERROR_BERR | HAL_FMPI2C_ERROR_OVR | HAL_FMPI2C_ERROR_ARLO)) != HAL_FMPI2C_ERROR_NONE) + { + FMPI2C_ITError(hfmpi2c, tmperror); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MasterTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MasterTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MasterRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MasterRxCpltCallback could be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_SlaveTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_SlaveTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_SlaveRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_SlaveRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref FMPI2C_XFERDIRECTION + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_FMPI2C_AddrCallback(FMPI2C_HandleTypeDef *hfmpi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_AddrCallback() could be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_ListenCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_ListenCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Memory Tx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MemTxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MemTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Memory Rx Transfer completed callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_MemRxCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_MemRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief FMPI2C error callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_ErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief FMPI2C abort callback. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval None + */ +__weak void HAL_FMPI2C_AbortCpltCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPI2C_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup FMPI2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State, Mode and Error functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permit to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the FMPI2C handle state. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval HAL state + */ +HAL_FMPI2C_StateTypeDef HAL_FMPI2C_GetState(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Return FMPI2C handle state */ + return hfmpi2c->State; +} + +/** + * @brief Returns the FMPI2C Master, Slave, Memory or no mode. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for FMPI2C module + * @retval HAL mode + */ +HAL_FMPI2C_ModeTypeDef HAL_FMPI2C_GetMode(FMPI2C_HandleTypeDef *hfmpi2c) +{ + return hfmpi2c->Mode; +} + +/** + * @brief Return the FMPI2C error code. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @retval FMPI2C Error Code + */ +uint32_t HAL_FMPI2C_GetError(FMPI2C_HandleTypeDef *hfmpi2c) +{ + return hfmpi2c->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup FMPI2C_Private_Functions + * @{ + */ + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Master_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint16_t devaddress; + uint32_t tmpITFlags = ITFlags; + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set corresponding Error Code */ + /* No need to generate STOP, it is automatically done */ + /* Error callback will be send during stop flag treatment */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET)) + { + /* Remove RXNE flag on temporary variable as read done */ + tmpITFlags &= ~FMPI2C_FLAG_RXNE; + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) == RESET) && \ + ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET))) + { + /* Write data to TXDR */ + if (hfmpi2c->XferCount != 0U) + { + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TCR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + devaddress = (uint16_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_SADD); + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME) + { + FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, + hfmpi2c->XferOptions, FMPI2C_NO_STARTSTOP); + } + else + { + FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP); + } + } + } + else + { + /* Call TxCpltCallback() if no stop mode is set */ + if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE) + { + /* Call FMPI2C Master Sequential complete process */ + FMPI2C_ITMasterSeqCplt(hfmpi2c); + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if (hfmpi2c->XferCount == 0U) + { + if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE) + { + /* Generate a stop condition in case of no transfer option */ + if (hfmpi2c->XferOptions == FMPI2C_NO_OPTION_FRAME) + { + /* Generate Stop */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP; + } + else + { + /* Call FMPI2C Master Sequential complete process */ + FMPI2C_ITMasterSeqCplt(hfmpi2c); + } + } + } + else + { + /* Wrong size Status regarding TC flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + else + { + /* Nothing to do */ + } + + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Master complete process */ + FMPI2C_ITMasterCplt(hfmpi2c, tmpITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Mem_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint32_t direction = FMPI2C_GENERATE_START_WRITE; + uint32_t tmpITFlags = ITFlags; + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set corresponding Error Code */ + /* No need to generate STOP, it is automatically done */ + /* Error callback will be send during stop flag treatment */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET)) + { + /* Remove RXNE flag on temporary variable as read done */ + tmpITFlags &= ~FMPI2C_FLAG_RXNE; + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET)) + { + if (hfmpi2c->Memaddress == 0xFFFFFFFFU) + { + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + else + { + /* Write LSB part of Memory Address */ + hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress; + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TCR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if ((hfmpi2c->XferCount != 0U) && (hfmpi2c->XferSize == 0U)) + { + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP); + } + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TC) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + direction = FMPI2C_GENERATE_START_READ; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_RELOAD_MODE, direction); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + + /* Set NBYTES to write and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_AUTOEND_MODE, direction); + } + } + else + { + /* Nothing to do */ + } + + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Master complete process */ + FMPI2C_ITMasterCplt(hfmpi2c, tmpITFlags); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with Interrupt. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Slave_ISR_IT(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint32_t tmpoptions = hfmpi2c->XferOptions; + uint32_t tmpITFlags = ITFlags; + + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + /* Check if STOPF is set */ + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Slave complete process */ + FMPI2C_ITSlaveCplt(hfmpi2c, tmpITFlags); + } + + if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Check that FMPI2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0*/ + /* So clear Flag NACKF only */ + if (hfmpi2c->XferCount == 0U) + { + if ((hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) && (tmpoptions == FMPI2C_FIRST_AND_LAST_FRAME)) + /* Same action must be done for (tmpoptions == FMPI2C_LAST_FRAME) which removed for + Warning[Pa134]: left and right operands are identical */ + { + /* Call FMPI2C Listen complete process */ + FMPI2C_ITListenCplt(hfmpi2c, tmpITFlags); + } + else if ((hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != FMPI2C_NO_OPTION_FRAME)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* Last Byte is Transmitted */ + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + else + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + } + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + if ((tmpoptions == FMPI2C_FIRST_FRAME) || (tmpoptions == FMPI2C_NEXT_FRAME)) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode); + } + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_RXI) != RESET)) + { + if (hfmpi2c->XferCount > 0U) + { + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + + if ((hfmpi2c->XferCount == 0U) && \ + (tmpoptions != FMPI2C_NO_OPTION_FRAME)) + { + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_ADDR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_ADDRI) != RESET)) + { + FMPI2C_ITAddrCplt(hfmpi2c, tmpITFlags); + } + else if ((FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_TXIS) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET)) + { + /* Write data to TXDR only if XferCount not reach "0" */ + /* A TXIS flag can be set, during STOP treatment */ + /* Check if all Data have already been sent */ + /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */ + if (hfmpi2c->XferCount > 0U) + { + /* Write data to TXDR */ + hfmpi2c->Instance->TXDR = *hfmpi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + hfmpi2c->XferCount--; + hfmpi2c->XferSize--; + } + else + { + if ((tmpoptions == FMPI2C_NEXT_FRAME) || (tmpoptions == FMPI2C_FIRST_FRAME)) + { + /* Last Byte is Transmitted */ + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + } + } + else + { + /* Nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode with DMA. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Master_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint16_t devaddress; + uint32_t xfermode; + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set corresponding Error Code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + /* No need to generate STOP, it is automatically done */ + /* But enable STOP interrupt, to treat it */ + /* Error callback will be send during stop flag treatment */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT); + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TCR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + /* Disable TC interrupt */ + __HAL_FMPI2C_DISABLE_IT(hfmpi2c, FMPI2C_IT_TCI); + + if (hfmpi2c->XferCount != 0U) + { + /* Recover Slave address */ + devaddress = (uint16_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_SADD); + + /* Prepare the new XferSize to transfer */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + xfermode = FMPI2C_RELOAD_MODE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME) + { + xfermode = hfmpi2c->XferOptions; + } + else + { + xfermode = FMPI2C_AUTOEND_MODE; + } + } + + /* Set the new XferSize in Nbytes register */ + FMPI2C_TransferConfig(hfmpi2c, devaddress, (uint8_t)hfmpi2c->XferSize, xfermode, FMPI2C_NO_STARTSTOP); + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Enable DMA Request */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + } + else + { + /* Call TxCpltCallback() if no stop mode is set */ + if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE) + { + /* Call FMPI2C Master Sequential complete process */ + FMPI2C_ITMasterSeqCplt(hfmpi2c); + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TC) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if (hfmpi2c->XferCount == 0U) + { + if (FMPI2C_GET_STOP_MODE(hfmpi2c) != FMPI2C_AUTOEND_MODE) + { + /* Generate a stop condition in case of no transfer option */ + if (hfmpi2c->XferOptions == FMPI2C_NO_OPTION_FRAME) + { + /* Generate Stop */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP; + } + else + { + /* Call FMPI2C Master Sequential complete process */ + FMPI2C_ITMasterSeqCplt(hfmpi2c); + } + } + } + else + { + /* Wrong size Status regarding TC flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Master complete process */ + FMPI2C_ITMasterCplt(hfmpi2c, ITFlags); + } + else + { + /* Nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Memory Mode with DMA. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Mem_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint32_t direction = FMPI2C_GENERATE_START_WRITE; + + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set corresponding Error Code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + /* No need to generate STOP, it is automatically done */ + /* But enable STOP interrupt, to treat it */ + /* Error callback will be send during stop flag treatment */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT); + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TXIS) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TXI) != RESET)) + { + /* Write LSB part of Memory Address */ + hfmpi2c->Instance->TXDR = hfmpi2c->Memaddress; + + /* Reset Memaddress content */ + hfmpi2c->Memaddress = 0xFFFFFFFFU; + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TCR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + /* Enable only Error interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_ERROR_IT); + + if (hfmpi2c->XferCount != 0U) + { + /* Prepare the new XferSize to transfer */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_RELOAD_MODE, FMPI2C_NO_STARTSTOP); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_AUTOEND_MODE, FMPI2C_NO_STARTSTOP); + } + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Enable DMA Request */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + } + else + { + /* Wrong size Status regarding TCR flag event */ + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_SIZE); + } + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_TC) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_TCI) != RESET)) + { + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + direction = FMPI2C_GENERATE_START_READ; + } + + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + + /* Set NBYTES to write and reload if hfmpi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_RELOAD_MODE, direction); + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + + /* Set NBYTES to write and generate RESTART */ + FMPI2C_TransferConfig(hfmpi2c, (uint16_t)hfmpi2c->Devaddress, (uint8_t)hfmpi2c->XferSize, + FMPI2C_AUTOEND_MODE, direction); + } + + /* Update XferCount value */ + hfmpi2c->XferCount -= hfmpi2c->XferSize; + + /* Enable DMA Request */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_RXDMAEN; + } + else + { + hfmpi2c->Instance->CR1 |= FMPI2C_CR1_TXDMAEN; + } + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Master complete process */ + FMPI2C_ITMasterCplt(hfmpi2c, ITFlags); + } + else + { + /* Nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode with DMA. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param ITFlags Interrupt flags to handle. + * @param ITSources Interrupt sources enabled. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_Slave_ISR_DMA(struct __FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags, + uint32_t ITSources) +{ + uint32_t tmpoptions = hfmpi2c->XferOptions; + uint32_t treatdmanack = 0U; + HAL_FMPI2C_StateTypeDef tmpstate; + + /* Process locked */ + __HAL_LOCK(hfmpi2c); + + /* Check if STOPF is set */ + if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_STOPF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_STOPI) != RESET)) + { + /* Call FMPI2C Slave complete process */ + FMPI2C_ITSlaveCplt(hfmpi2c, ITFlags); + } + + if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_AF) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_NACKI) != RESET)) + { + /* Check that FMPI2C transfer finished */ + /* if yes, normal use case, a NACK is sent by the MASTER when Transfer is finished */ + /* Mean XferCount == 0 */ + /* So clear Flag NACKF only */ + if ((FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_TXDMAEN) != RESET) || + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_RXDMAEN) != RESET)) + { + /* Split check of hdmarx, for MISRA compliance */ + if (hfmpi2c->hdmarx != NULL) + { + if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_RXDMAEN) != RESET) + { + if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U) + { + treatdmanack = 1U; + } + } + } + + /* Split check of hdmatx, for MISRA compliance */ + if (hfmpi2c->hdmatx != NULL) + { + if (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_CR1_TXDMAEN) != RESET) + { + if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U) + { + treatdmanack = 1U; + } + } + } + + if (treatdmanack == 1U) + { + if ((hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) && (tmpoptions == FMPI2C_FIRST_AND_LAST_FRAME)) + /* Same action must be done for (tmpoptions == FMPI2C_LAST_FRAME) which removed for + Warning[Pa134]: left and right operands are identical */ + { + /* Call FMPI2C Listen complete process */ + FMPI2C_ITListenCplt(hfmpi2c, ITFlags); + } + else if ((hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) && (tmpoptions != FMPI2C_NO_OPTION_FRAME)) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* Last Byte is Transmitted */ + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + else + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + } + } + else + { + /* if no, error use case, a Non-Acknowledge of last Data is generated by the MASTER*/ + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + + /* Store current hfmpi2c->State, solve MISRA2012-Rule-13.5 */ + tmpstate = hfmpi2c->State; + + if ((tmpoptions == FMPI2C_FIRST_FRAME) || (tmpoptions == FMPI2C_NEXT_FRAME)) + { + if ((tmpstate == HAL_FMPI2C_STATE_BUSY_TX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)) + { + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX; + } + else if ((tmpstate == HAL_FMPI2C_STATE_BUSY_RX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)) + { + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX; + } + else + { + /* Do nothing */ + } + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode); + } + } + } + else + { + /* Only Clear NACK Flag, no DMA treatment is pending */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + } + } + else if ((FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_ADDR) != RESET) && \ + (FMPI2C_CHECK_IT_SOURCE(ITSources, FMPI2C_IT_ADDRI) != RESET)) + { + FMPI2C_ITAddrCplt(hfmpi2c, ITFlags); + } + else + { + /* Nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for write request. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_RequestMemoryWrite(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, + uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, + uint32_t Tickstart) +{ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_RELOAD_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send LSB of Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TCR flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TCR, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for read request. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_RequestMemoryRead(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, + uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, + uint32_t Tickstart) +{ + FMPI2C_TransferConfig(hfmpi2c, DevAddress, (uint8_t)MemAddSize, FMPI2C_SOFTEND_MODE, FMPI2C_GENERATE_START_WRITE); + + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == FMPI2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXIS flag is set */ + if (FMPI2C_WaitOnTXISFlagUntilTimeout(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send LSB of Memory Address */ + hfmpi2c->Instance->TXDR = FMPI2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TC flag is set */ + if (FMPI2C_WaitOnFlagUntilTimeout(hfmpi2c, FMPI2C_FLAG_TC, RESET, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief FMPI2C Address complete process callback. + * @param hfmpi2c FMPI2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void FMPI2C_ITAddrCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags) +{ + uint8_t transferdirection; + uint16_t slaveaddrcode; + uint16_t ownadd1code; + uint16_t ownadd2code; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(ITFlags); + + /* In case of Listen state, need to inform upper layer of address match code event */ + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) == (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + transferdirection = FMPI2C_GET_DIR(hfmpi2c); + slaveaddrcode = FMPI2C_GET_ADDR_MATCH(hfmpi2c); + ownadd1code = FMPI2C_GET_OWN_ADDRESS1(hfmpi2c); + ownadd2code = FMPI2C_GET_OWN_ADDRESS2(hfmpi2c); + + /* If 10bits addressing mode is selected */ + if (hfmpi2c->Init.AddressingMode == FMPI2C_ADDRESSINGMODE_10BIT) + { + if ((slaveaddrcode & SLAVE_ADDR_MSK) == ((ownadd1code >> SLAVE_ADDR_SHIFT) & SLAVE_ADDR_MSK)) + { + slaveaddrcode = ownadd1code; + hfmpi2c->AddrEventCount++; + if (hfmpi2c->AddrEventCount == 2U) + { + /* Reset Address Event counter */ + hfmpi2c->AddrEventCount = 0U; + + /* Clear ADDR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call Slave Addr callback */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#else + HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + } + else + { + slaveaddrcode = ownadd2code; + + /* Disable ADDR Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call Slave Addr callback */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#else + HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + } + /* else 7 bits addressing mode is selected */ + else + { + /* Disable ADDR Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call Slave Addr callback */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#else + HAL_FMPI2C_AddrCallback(hfmpi2c, transferdirection, slaveaddrcode); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + } + /* Else clear address flag only */ + else + { + /* Clear ADDR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + } +} + +/** + * @brief FMPI2C Master sequential complete process. + * @param hfmpi2c FMPI2C handle. + * @retval None + */ +static void FMPI2C_ITMasterSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* Reset FMPI2C handle mode */ + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* No Generate Stop, to permit restart mode */ + /* The stop will be done at the end of transfer, when FMPI2C_AUTOEND_MODE enable */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX) + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX; + hfmpi2c->XferISR = NULL; + + /* Disable Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MasterTxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MasterTxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX */ + else + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX; + hfmpi2c->XferISR = NULL; + + /* Disable Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MasterRxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MasterRxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } +} + +/** + * @brief FMPI2C Slave sequential complete process. + * @param hfmpi2c FMPI2C handle. + * @retval None + */ +static void FMPI2C_ITSlaveSeqCplt(FMPI2C_HandleTypeDef *hfmpi2c) +{ + uint32_t tmpcr1value = READ_REG(hfmpi2c->Instance->CR1); + + /* Reset FMPI2C handle mode */ + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* If a DMA is ongoing, Update handle size context */ + if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_TXDMAEN) != RESET) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + } + else if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_RXDMAEN) != RESET) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + } + else + { + /* Do nothing */ + } + + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) + { + /* Remove HAL_FMPI2C_STATE_SLAVE_BUSY_TX, keep only HAL_FMPI2C_STATE_LISTEN */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX; + + /* Disable Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->SlaveTxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_SlaveTxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX_LISTEN) + { + /* Remove HAL_FMPI2C_STATE_SLAVE_BUSY_RX, keep only HAL_FMPI2C_STATE_LISTEN */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX; + + /* Disable Interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->SlaveRxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_SlaveRxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief FMPI2C Master complete process. + * @param hfmpi2c FMPI2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void FMPI2C_ITMasterCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags) +{ + uint32_t tmperror; + uint32_t tmpITFlags = ITFlags; + __IO uint32_t tmpreg; + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Disable Interrupts and Store Previous state */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_TX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_TX; + } + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_MASTER_BUSY_RX; + } + else + { + /* Do nothing */ + } + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + /* Reset handle parameters */ + hfmpi2c->XferISR = NULL; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + + if (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_AF) != RESET) + { + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Set acknowledge error code */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + } + + /* Fetch Last receive data if any */ + if ((hfmpi2c->State == HAL_FMPI2C_STATE_ABORT) && (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET)) + { + /* Read data from RXDR */ + tmpreg = (uint8_t)hfmpi2c->Instance->RXDR; + UNUSED(tmpreg); + } + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* Store current volatile hfmpi2c->ErrorCode, misra rule */ + tmperror = hfmpi2c->ErrorCode; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if ((hfmpi2c->State == HAL_FMPI2C_STATE_ABORT) || (tmperror != HAL_FMPI2C_ERROR_NONE)) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode); + } + /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX */ + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_TX) + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MEM) + { + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MemTxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MemTxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + else + { + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MasterTxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MasterTxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + } + /* hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX */ + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + if (hfmpi2c->Mode == HAL_FMPI2C_MODE_MEM) + { + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MemRxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MemRxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + else + { + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->MasterRxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_MasterRxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief FMPI2C Slave complete process. + * @param hfmpi2c FMPI2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void FMPI2C_ITSlaveCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags) +{ + uint32_t tmpcr1value = READ_REG(hfmpi2c->Instance->CR1); + uint32_t tmpITFlags = ITFlags; + HAL_FMPI2C_StateTypeDef tmpstate = hfmpi2c->State; + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Disable Interrupts and Store Previous state */ + if ((tmpstate == HAL_FMPI2C_STATE_BUSY_TX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN)) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_TX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_TX; + } + else if ((tmpstate == HAL_FMPI2C_STATE_BUSY_RX) || (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)) + { + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT); + hfmpi2c->PreviousState = FMPI2C_STATE_SLAVE_BUSY_RX; + } + else + { + /* Do nothing */ + } + + /* Disable Address Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* If a DMA is ongoing, Update handle size context */ + if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_TXDMAEN) != RESET) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + if (hfmpi2c->hdmatx != NULL) + { + hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx); + } + } + else if (FMPI2C_CHECK_IT_SOURCE(tmpcr1value, FMPI2C_CR1_RXDMAEN) != RESET) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + if (hfmpi2c->hdmarx != NULL) + { + hfmpi2c->XferCount = (uint16_t)FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx); + } + } + else + { + /* Do nothing */ + } + + /* Store Last receive data if any */ + if (FMPI2C_CHECK_FLAG(tmpITFlags, FMPI2C_FLAG_RXNE) != RESET) + { + /* Remove RXNE flag on temporary variable as read done */ + tmpITFlags &= ~FMPI2C_FLAG_RXNE; + + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + if ((hfmpi2c->XferSize > 0U)) + { + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + } + } + + /* All data are not transferred, so set error code accordingly */ + if (hfmpi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + } + + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + hfmpi2c->XferISR = NULL; + + if (hfmpi2c->ErrorCode != HAL_FMPI2C_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, hfmpi2c->ErrorCode); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ + if (hfmpi2c->State == HAL_FMPI2C_STATE_LISTEN) + { + /* Call FMPI2C Listen complete process */ + FMPI2C_ITListenCplt(hfmpi2c, tmpITFlags); + } + } + else if (hfmpi2c->XferOptions != FMPI2C_NO_OPTION_FRAME) + { + /* Call the Sequential Complete callback, to inform upper layer of the end of Transfer */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->ListenCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_ListenCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + /* Call the corresponding callback to inform upper layer of End of Transfer */ + else if (hfmpi2c->State == HAL_FMPI2C_STATE_BUSY_RX) + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->SlaveRxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_SlaveRxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + else + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->SlaveTxCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_SlaveTxCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } +} + +/** + * @brief FMPI2C Listen complete process. + * @param hfmpi2c FMPI2C handle. + * @param ITFlags Interrupt flags to handle. + * @retval None + */ +static void FMPI2C_ITListenCplt(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ITFlags) +{ + /* Reset handle parameters */ + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + hfmpi2c->XferISR = NULL; + + /* Store Last receive data if any */ + if (FMPI2C_CHECK_FLAG(ITFlags, FMPI2C_FLAG_RXNE) != RESET) + { + /* Read data from RXDR */ + *hfmpi2c->pBuffPtr = (uint8_t)hfmpi2c->Instance->RXDR; + + /* Increment Buffer pointer */ + hfmpi2c->pBuffPtr++; + + if ((hfmpi2c->XferSize > 0U)) + { + hfmpi2c->XferSize--; + hfmpi2c->XferCount--; + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_AF; + } + } + + /* Disable all Interrupts*/ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT); + + /* Clear NACK Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->ListenCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_ListenCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ +} + +/** + * @brief FMPI2C interrupts error process. + * @param hfmpi2c FMPI2C handle. + * @param ErrorCode Error code to handle. + * @retval None + */ +static void FMPI2C_ITError(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t ErrorCode) +{ + HAL_FMPI2C_StateTypeDef tmpstate = hfmpi2c->State; + uint32_t tmppreviousstate; + + /* Reset handle parameters */ + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + hfmpi2c->XferOptions = FMPI2C_NO_OPTION_FRAME; + hfmpi2c->XferCount = 0U; + + /* Set new error code */ + hfmpi2c->ErrorCode |= ErrorCode; + + /* Disable Interrupts */ + if ((tmpstate == HAL_FMPI2C_STATE_LISTEN) || + (tmpstate == HAL_FMPI2C_STATE_BUSY_TX_LISTEN) || + (tmpstate == HAL_FMPI2C_STATE_BUSY_RX_LISTEN)) + { + /* Disable all interrupts, except interrupts related to LISTEN state */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT); + + /* keep HAL_FMPI2C_STATE_LISTEN if set */ + hfmpi2c->State = HAL_FMPI2C_STATE_LISTEN; + hfmpi2c->XferISR = FMPI2C_Slave_ISR_IT; + } + else + { + /* Disable all interrupts */ + FMPI2C_Disable_IRQ(hfmpi2c, FMPI2C_XFER_LISTEN_IT | FMPI2C_XFER_RX_IT | FMPI2C_XFER_TX_IT); + + /* If state is an abort treatment on going, don't change state */ + /* This change will be do later */ + if (hfmpi2c->State != HAL_FMPI2C_STATE_ABORT) + { + /* Set HAL_FMPI2C_STATE_READY */ + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + } + hfmpi2c->XferISR = NULL; + } + + /* Abort DMA TX transfer if any */ + tmppreviousstate = hfmpi2c->PreviousState; + if ((hfmpi2c->hdmatx != NULL) && ((tmppreviousstate == FMPI2C_STATE_MASTER_BUSY_TX) || \ + (tmppreviousstate == FMPI2C_STATE_SLAVE_BUSY_TX))) + { + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_TXDMAEN) == FMPI2C_CR1_TXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + } + + if (HAL_DMA_GetState(hfmpi2c->hdmatx) != HAL_DMA_STATE_READY) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmatx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hfmpi2c->hdmatx->XferAbortCallback(hfmpi2c->hdmatx); + } + } + else + { + FMPI2C_TreatErrorCallback(hfmpi2c); + } + } + /* Abort DMA RX transfer if any */ + else if ((hfmpi2c->hdmarx != NULL) && ((tmppreviousstate == FMPI2C_STATE_MASTER_BUSY_RX) || \ + (tmppreviousstate == FMPI2C_STATE_SLAVE_BUSY_RX))) + { + if ((hfmpi2c->Instance->CR1 & FMPI2C_CR1_RXDMAEN) == FMPI2C_CR1_RXDMAEN) + { + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + } + + if (HAL_DMA_GetState(hfmpi2c->hdmarx) != HAL_DMA_STATE_READY) + { + /* Set the FMPI2C DMA Abort callback : + will lead to call HAL_FMPI2C_ErrorCallback() at end of DMA abort procedure */ + hfmpi2c->hdmarx->XferAbortCallback = FMPI2C_DMAAbort; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hfmpi2c->hdmarx) != HAL_OK) + { + /* Call Directly hfmpi2c->hdmarx->XferAbortCallback function in case of error */ + hfmpi2c->hdmarx->XferAbortCallback(hfmpi2c->hdmarx); + } + } + else + { + FMPI2C_TreatErrorCallback(hfmpi2c); + } + } + else + { + FMPI2C_TreatErrorCallback(hfmpi2c); + } +} + +/** + * @brief FMPI2C Error callback treatment. + * @param hfmpi2c FMPI2C handle. + * @retval None + */ +static void FMPI2C_TreatErrorCallback(FMPI2C_HandleTypeDef *hfmpi2c) +{ + if (hfmpi2c->State == HAL_FMPI2C_STATE_ABORT) + { + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->AbortCpltCallback(hfmpi2c); +#else + HAL_FMPI2C_AbortCpltCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } + else + { + hfmpi2c->PreviousState = FMPI2C_STATE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPI2C_REGISTER_CALLBACKS == 1) + hfmpi2c->ErrorCallback(hfmpi2c); +#else + HAL_FMPI2C_ErrorCallback(hfmpi2c); +#endif /* USE_HAL_FMPI2C_REGISTER_CALLBACKS */ + } +} + +/** + * @brief FMPI2C Tx data register flush process. + * @param hfmpi2c FMPI2C handle. + * @retval None + */ +static void FMPI2C_Flush_TXDR(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* If a pending TXIS flag is set */ + /* Write a dummy data in TXDR to clear it */ + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) != RESET) + { + hfmpi2c->Instance->TXDR = 0x00U; + } + + /* Flush TX register if not empty */ + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXE) == RESET) + { + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_TXE); + } +} + +/** + * @brief DMA FMPI2C master transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void FMPI2C_DMAMasterTransmitCplt(DMA_HandleTypeDef *hdma) +{ + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hfmpi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hfmpi2c->pBuffPtr += hfmpi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + } + + /* Enable the DMA stream */ + if (HAL_DMA_Start_IT(hfmpi2c->hdmatx, (uint32_t)hfmpi2c->pBuffPtr, (uint32_t)&hfmpi2c->Instance->TXDR, + hfmpi2c->XferSize) != HAL_OK) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA); + } + else + { + /* Enable TC interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RELOAD_IT); + } + } +} + +/** + * @brief DMA FMPI2C slave transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void FMPI2C_DMASlaveTransmitCplt(DMA_HandleTypeDef *hdma) +{ + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + uint32_t tmpoptions = hfmpi2c->XferOptions; + + if ((tmpoptions == FMPI2C_NEXT_FRAME) || (tmpoptions == FMPI2C_FIRST_FRAME)) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_TXDMAEN; + + /* Last Byte is Transmitted */ + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + else + { + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ + } +} + +/** + * @brief DMA FMPI2C master receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void FMPI2C_DMAMasterReceiveCplt(DMA_HandleTypeDef *hdma) +{ + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + /* If last transfer, enable STOP interrupt */ + if (hfmpi2c->XferCount == 0U) + { + /* Enable STOP interrupt */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_CPLT_IT); + } + /* else prepare a new DMA transfer and enable TCReload interrupt */ + else + { + /* Update Buffer pointer */ + hfmpi2c->pBuffPtr += hfmpi2c->XferSize; + + /* Set the XferSize to transfer */ + if (hfmpi2c->XferCount > MAX_NBYTE_SIZE) + { + hfmpi2c->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpi2c->XferSize = hfmpi2c->XferCount; + } + + /* Enable the DMA stream */ + if (HAL_DMA_Start_IT(hfmpi2c->hdmarx, (uint32_t)&hfmpi2c->Instance->RXDR, (uint32_t)hfmpi2c->pBuffPtr, + hfmpi2c->XferSize) != HAL_OK) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA); + } + else + { + /* Enable TC interrupts */ + FMPI2C_Enable_IRQ(hfmpi2c, FMPI2C_XFER_RELOAD_IT); + } + } +} + +/** + * @brief DMA FMPI2C slave receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void FMPI2C_DMASlaveReceiveCplt(DMA_HandleTypeDef *hdma) +{ + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + uint32_t tmpoptions = hfmpi2c->XferOptions; + + if ((FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U) && \ + (tmpoptions != FMPI2C_NO_OPTION_FRAME)) + { + /* Disable DMA Request */ + hfmpi2c->Instance->CR1 &= ~FMPI2C_CR1_RXDMAEN; + + /* Call FMPI2C Slave Sequential complete process */ + FMPI2C_ITSlaveSeqCplt(hfmpi2c); + } + else + { + /* No specific action, Master fully manage the generation of STOP condition */ + /* Mean that this generation can arrive at any time, at the end or during DMA process */ + /* So STOP condition should be manage through Interrupt treatment */ + } +} + +/** + * @brief DMA FMPI2C communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void FMPI2C_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t treatdmaerror = 0U; + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + if (hfmpi2c->hdmatx != NULL) + { + if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmatx) == 0U) + { + treatdmaerror = 1U; + } + } + + if (hfmpi2c->hdmarx != NULL) + { + if (FMPI2C_GET_DMA_REMAIN_DATA(hfmpi2c->hdmarx) == 0U) + { + treatdmaerror = 1U; + } + } + + /* Check if a FIFO error is detected, if true normal use case, so no specific action to perform */ + if (!((HAL_DMA_GetError(hdma) == HAL_DMA_ERROR_FE)) && (treatdmaerror != 0U)) + { + /* Disable Acknowledge */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_NACK; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + FMPI2C_ITError(hfmpi2c, HAL_FMPI2C_ERROR_DMA); + } +} + +/** + * @brief DMA FMPI2C communication abort callback + * (To be called at end of DMA Abort procedure). + * @param hdma DMA handle. + * @retval None + */ +static void FMPI2C_DMAAbort(DMA_HandleTypeDef *hdma) +{ + /* Derogation MISRAC2012-Rule-11.5 */ + FMPI2C_HandleTypeDef *hfmpi2c = (FMPI2C_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); + + /* Reset AbortCpltCallback */ + if (hfmpi2c->hdmatx != NULL) + { + hfmpi2c->hdmatx->XferAbortCallback = NULL; + } + if (hfmpi2c->hdmarx != NULL) + { + hfmpi2c->hdmarx->XferAbortCallback = NULL; + } + + FMPI2C_TreatErrorCallback(hfmpi2c); +} + +/** + * @brief This function handles FMPI2C Communication Timeout. It waits + * until a flag is no longer in the specified status. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param Flag Specifies the FMPI2C flag to check. + * @param Status The actual Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_WaitOnFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Flag, FlagStatus Status, + uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, Flag) == Status)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles FMPI2C Communication Timeout for specific usage of TXIS flag. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_WaitOnTXISFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart) +{ + while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) == RESET) + { + /* Check if an error is detected */ + if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_TXIS) == RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles FMPI2C Communication Timeout for specific usage of STOP flag. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_WaitOnSTOPFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart) +{ + while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET) + { + /* Check if an error is detected */ + if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles FMPI2C Communication Timeout for specific usage of RXNE flag. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_WaitOnRXNEFlagUntilTimeout(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, + uint32_t Tickstart) +{ + while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == RESET) + { + /* Check if an error is detected */ + if (FMPI2C_IsErrorOccurred(hfmpi2c, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check if a STOPF is detected */ + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == SET) + { + /* Check if an RXNE is pending */ + /* Store Last receive data if any */ + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == SET) && (hfmpi2c->XferSize > 0U)) + { + /* Return HAL_OK */ + /* The Reading of data from RXDR will be done in caller function */ + return HAL_OK; + } + else + { + if (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_AF) == SET) + { + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_AF; + } + else + { + hfmpi2c->ErrorCode = HAL_FMPI2C_ERROR_NONE; + } + + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + + /* Check for the Timeout */ + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_RXNE) == RESET)) + { + hfmpi2c->ErrorCode |= HAL_FMPI2C_ERROR_TIMEOUT; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles errors detection during an FMPI2C Communication. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef FMPI2C_IsErrorOccurred(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t Timeout, uint32_t Tickstart) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t itflag = hfmpi2c->Instance->ISR; + uint32_t error_code = 0; + uint32_t tickstart = Tickstart; + uint32_t tmp1; + HAL_FMPI2C_ModeTypeDef tmp2; + + if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_AF)) + { + /* Clear NACKF Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_AF); + + /* Wait until STOP Flag is set or timeout occurred */ + /* AutoEnd should be initiate after AF */ + while ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET) && (status == HAL_OK)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + tmp1 = (uint32_t)(hfmpi2c->Instance->CR2 & FMPI2C_CR2_STOP); + tmp2 = hfmpi2c->Mode; + + /* In case of FMPI2C still busy, try to regenerate a STOP manually */ + if ((__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_BUSY) != RESET) && \ + (tmp1 != FMPI2C_CR2_STOP) && \ + (tmp2 != HAL_FMPI2C_MODE_SLAVE)) + { + /* Generate Stop */ + hfmpi2c->Instance->CR2 |= FMPI2C_CR2_STOP; + + /* Update Tick with new reference */ + tickstart = HAL_GetTick(); + } + + while (__HAL_FMPI2C_GET_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF) == RESET) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > FMPI2C_TIMEOUT_STOPF) + { + error_code |=HAL_FMPI2C_ERROR_TIMEOUT; + + status = HAL_ERROR; + + break; + } + } + } + } + } + + /* In case STOP Flag is detected, clear it */ + if (status == HAL_OK) + { + /* Clear STOP Flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_STOPF); + } + + error_code |= HAL_FMPI2C_ERROR_AF; + + status = HAL_ERROR; + } + + /* Refresh Content of Status register */ + itflag = hfmpi2c->Instance->ISR; + + /* Then verify if an additional errors occurs */ + /* Check if a Bus error occurred */ + if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_BERR)) + { + error_code |= HAL_FMPI2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_BERR); + + status = HAL_ERROR; + } + + /* Check if an Over-Run/Under-Run error occurred */ + if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_OVR)) + { + error_code |= HAL_FMPI2C_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_OVR); + + status = HAL_ERROR; + } + + /* Check if an Arbitration Loss error occurred */ + if (HAL_IS_BIT_SET(itflag, FMPI2C_FLAG_ARLO)) + { + error_code |= HAL_FMPI2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_FMPI2C_CLEAR_FLAG(hfmpi2c, FMPI2C_FLAG_ARLO); + + status = HAL_ERROR; + } + + if (status != HAL_OK) + { + /* Flush TX register */ + FMPI2C_Flush_TXDR(hfmpi2c); + + /* Clear Configuration Register 2 */ + FMPI2C_RESET_CR2(hfmpi2c); + + hfmpi2c->ErrorCode |= error_code; + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + hfmpi2c->Mode = HAL_FMPI2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + } + + return status; +} + +/** + * @brief Handles FMPI2Cx communication when starting transfer or during transfer (TC or TCR flag are set). + * @param hfmpi2c FMPI2C handle. + * @param DevAddress Specifies the slave address to be programmed. + * @param Size Specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param Mode New state of the FMPI2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_RELOAD_MODE Enable Reload mode . + * @arg @ref FMPI2C_AUTOEND_MODE Enable Automatic end mode. + * @arg @ref FMPI2C_SOFTEND_MODE Enable Software end mode. + * @param Request New state of the FMPI2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref FMPI2C_NO_STARTSTOP Don't Generate stop and start condition. + * @arg @ref FMPI2C_GENERATE_STOP Generate stop condition (Size should be set to 0). + * @arg @ref FMPI2C_GENERATE_START_READ Generate Restart for read request. + * @arg @ref FMPI2C_GENERATE_START_WRITE Generate Restart for write request. + * @retval None + */ +static void FMPI2C_TransferConfig(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, + uint32_t Request) +{ + /* Check the parameters */ + assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance)); + assert_param(IS_TRANSFER_MODE(Mode)); + assert_param(IS_TRANSFER_REQUEST(Request)); + + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp = ((uint32_t)(((uint32_t)DevAddress & FMPI2C_CR2_SADD) | \ + (((uint32_t)Size << FMPI2C_CR2_NBYTES_Pos) & FMPI2C_CR2_NBYTES) | \ + (uint32_t)Mode | (uint32_t)Request) & (~0x80000000U)); + + /* update CR2 register */ + MODIFY_REG(hfmpi2c->Instance->CR2, \ + ((FMPI2C_CR2_SADD | FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | \ + (FMPI2C_CR2_RD_WRN & (uint32_t)(Request >> (31U - FMPI2C_CR2_RD_WRN_Pos))) | \ + FMPI2C_CR2_START | FMPI2C_CR2_STOP)), tmp); +} + +/** + * @brief Manage the enabling of Interrupts. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param InterruptRequest Value of @ref FMPI2C_Interrupt_configuration_definition. + * @retval None + */ +static void FMPI2C_Enable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((hfmpi2c->XferISR == FMPI2C_Master_ISR_DMA) || \ + (hfmpi2c->XferISR == FMPI2C_Slave_ISR_DMA)) + { + if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK and ADDR interrupts */ + tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI; + } + + if (InterruptRequest == FMPI2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI; + } + + if (InterruptRequest == FMPI2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= (FMPI2C_IT_STOPI | FMPI2C_IT_TCI); + } + + if (InterruptRequest == FMPI2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= FMPI2C_IT_TCI; + } + } + else + { + if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT) + { + /* Enable ERR, STOP, NACK, and ADDR interrupts */ + tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI; + } + + if ((InterruptRequest & FMPI2C_XFER_TX_IT) == FMPI2C_XFER_TX_IT) + { + /* Enable ERR, TC, STOP, NACK and RXI interrupts */ + tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_TXI; + } + + if ((InterruptRequest & FMPI2C_XFER_RX_IT) == FMPI2C_XFER_RX_IT) + { + /* Enable ERR, TC, STOP, NACK and TXI interrupts */ + tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_TCI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_RXI; + } + + if (InterruptRequest == FMPI2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI; + } + + if (InterruptRequest == FMPI2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= FMPI2C_IT_STOPI; + } + } + + /* Enable interrupts only at the end */ + /* to avoid the risk of FMPI2C interrupt handle execution before */ + /* all interrupts requested done */ + __HAL_FMPI2C_ENABLE_IT(hfmpi2c, tmpisr); +} + +/** + * @brief Manage the disabling of Interrupts. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2C. + * @param InterruptRequest Value of @ref FMPI2C_Interrupt_configuration_definition. + * @retval None + */ +static void FMPI2C_Disable_IRQ(FMPI2C_HandleTypeDef *hfmpi2c, uint16_t InterruptRequest) +{ + uint32_t tmpisr = 0U; + + if ((InterruptRequest & FMPI2C_XFER_TX_IT) == FMPI2C_XFER_TX_IT) + { + /* Disable TC and TXI interrupts */ + tmpisr |= FMPI2C_IT_TCI | FMPI2C_IT_TXI; + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) != (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI; + } + } + + if ((InterruptRequest & FMPI2C_XFER_RX_IT) == FMPI2C_XFER_RX_IT) + { + /* Disable TC and RXI interrupts */ + tmpisr |= FMPI2C_IT_TCI | FMPI2C_IT_RXI; + + if (((uint32_t)hfmpi2c->State & (uint32_t)HAL_FMPI2C_STATE_LISTEN) != (uint32_t)HAL_FMPI2C_STATE_LISTEN) + { + /* Disable NACK and STOP interrupts */ + tmpisr |= FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI; + } + } + + if ((InterruptRequest & FMPI2C_XFER_LISTEN_IT) == FMPI2C_XFER_LISTEN_IT) + { + /* Disable ADDR, NACK and STOP interrupts */ + tmpisr |= FMPI2C_IT_ADDRI | FMPI2C_IT_STOPI | FMPI2C_IT_NACKI | FMPI2C_IT_ERRI; + } + + if (InterruptRequest == FMPI2C_XFER_ERROR_IT) + { + /* Enable ERR and NACK interrupts */ + tmpisr |= FMPI2C_IT_ERRI | FMPI2C_IT_NACKI; + } + + if (InterruptRequest == FMPI2C_XFER_CPLT_IT) + { + /* Enable STOP interrupts */ + tmpisr |= FMPI2C_IT_STOPI; + } + + if (InterruptRequest == FMPI2C_XFER_RELOAD_IT) + { + /* Enable TC interrupts */ + tmpisr |= FMPI2C_IT_TCI; + } + + /* Disable interrupts only at the end */ + /* to avoid a breaking situation like at "t" time */ + /* all disable interrupts request are not done */ + __HAL_FMPI2C_DISABLE_IT(hfmpi2c, tmpisr); +} + +/** + * @brief Convert FMPI2Cx OTHER_xxx XferOptions to functional XferOptions. + * @param hfmpi2c FMPI2C handle. + * @retval None + */ +static void FMPI2C_ConvertOtherXferOptions(FMPI2C_HandleTypeDef *hfmpi2c) +{ + /* if user set XferOptions to FMPI2C_OTHER_FRAME */ + /* it request implicitly to generate a restart condition */ + /* set XferOptions to FMPI2C_FIRST_FRAME */ + if (hfmpi2c->XferOptions == FMPI2C_OTHER_FRAME) + { + hfmpi2c->XferOptions = FMPI2C_FIRST_FRAME; + } + /* else if user set XferOptions to FMPI2C_OTHER_AND_LAST_FRAME */ + /* it request implicitly to generate a restart condition */ + /* then generate a stop condition at the end of transfer */ + /* set XferOptions to FMPI2C_FIRST_AND_LAST_FRAME */ + else if (hfmpi2c->XferOptions == FMPI2C_OTHER_AND_LAST_FRAME) + { + hfmpi2c->XferOptions = FMPI2C_FIRST_AND_LAST_FRAME; + } + else + { + /* Nothing to do */ + } +} + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#endif /* HAL_FMPI2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c new file mode 100644 index 0000000..267a9ef --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpi2c_ex.c @@ -0,0 +1,258 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpi2c_ex.c + * @author MCD Application Team + * @brief FMPI2C Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of FMPI2C Extended peripheral: + * + Filter Mode Functions + * + FastModePlus 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 + ============================================================================== + ##### FMPI2C peripheral Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the FMPI2C interface for STM32F4xx + devices contains the following additional features + + (+) Possibility to disable or enable Analog Noise Filter + (+) Use of a configured Digital Noise Filter + (+) Disable or enable Fast Mode Plus + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to: + (#) Configure FMPI2C Analog noise filter using the function HAL_FMPI2CEx_ConfigAnalogFilter() + (#) Configure FMPI2C Digital noise filter using the function HAL_FMPI2CEx_ConfigDigitalFilter() + (#) Configure the enable or disable of fast mode plus driving capability using the functions : + (++) HAL_FMPI2CEx_EnableFastModePlus() + (++) HAL_FMPI2CEx_DisableFastModePlus() + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup FMPI2CEx FMPI2CEx + * @brief FMPI2C Extended HAL module driver + * @{ + */ + +#ifdef HAL_FMPI2C_MODULE_ENABLED +#if defined(FMPI2C_CR1_PE) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup FMPI2CEx_Exported_Functions FMPI2C Extended Exported Functions + * @{ + */ + +/** @defgroup FMPI2CEx_Exported_Functions_Group1 Filter Mode Functions + * @brief Filter Mode Functions + * +@verbatim + =============================================================================== + ##### Filter Mode Functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Noise Filters + +@endverbatim + * @{ + */ + +/** + * @brief Configure FMPI2C Analog noise filter. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2Cx peripheral. + * @param AnalogFilter New state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2CEx_ConfigAnalogFilter(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance)); + assert_param(IS_FMPI2C_ANALOG_FILTER(AnalogFilter)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY; + + /* Disable the selected FMPI2C peripheral */ + __HAL_FMPI2C_DISABLE(hfmpi2c); + + /* Reset FMPI2Cx ANOFF bit */ + hfmpi2c->Instance->CR1 &= ~(FMPI2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + hfmpi2c->Instance->CR1 |= AnalogFilter; + + __HAL_FMPI2C_ENABLE(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configure FMPI2C Digital noise filter. + * @param hfmpi2c Pointer to a FMPI2C_HandleTypeDef structure that contains + * the configuration information for the specified FMPI2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPI2CEx_ConfigDigitalFilter(FMPI2C_HandleTypeDef *hfmpi2c, uint32_t DigitalFilter) +{ + uint32_t tmpreg; + + /* Check the parameters */ + assert_param(IS_FMPI2C_ALL_INSTANCE(hfmpi2c->Instance)); + assert_param(IS_FMPI2C_DIGITAL_FILTER(DigitalFilter)); + + if (hfmpi2c->State == HAL_FMPI2C_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_BUSY; + + /* Disable the selected FMPI2C peripheral */ + __HAL_FMPI2C_DISABLE(hfmpi2c); + + /* Get the old register value */ + tmpreg = hfmpi2c->Instance->CR1; + + /* Reset FMPI2Cx DNF bits [11:8] */ + tmpreg &= ~(FMPI2C_CR1_DNF); + + /* Set FMPI2Cx DNF coefficient */ + tmpreg |= DigitalFilter << 8U; + + /* Store the new register value */ + hfmpi2c->Instance->CR1 = tmpreg; + + __HAL_FMPI2C_ENABLE(hfmpi2c); + + hfmpi2c->State = HAL_FMPI2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @} + */ + +/** @defgroup FMPI2CEx_Exported_Functions_Group3 Fast Mode Plus Functions + * @brief Fast Mode Plus Functions + * +@verbatim + =============================================================================== + ##### Fast Mode Plus Functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Fast Mode Plus + +@endverbatim + * @{ + */ + +/** + * @brief Enable the FMPI2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref FMPI2CEx_FastModePlus values + * @note For FMPI2C1, fast mode plus driving capability can be enabled on all selected + * FMPI2C1 pins using FMPI2C_FASTMODEPLUS_FMPI2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining FMPI2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be enabled only by using FMPI2C_FASTMODEPLUS_FMPI2C1 parameter. + * @retval None + */ +void HAL_FMPI2CEx_EnableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_FMPI2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Enable fast mode plus driving capability for selected pin */ + SET_BIT(SYSCFG->CFGR, (uint32_t)ConfigFastModePlus); +} + +/** + * @brief Disable the FMPI2C fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref FMPI2CEx_FastModePlus values + * @note For FMPI2C1, fast mode plus driving capability can be disabled on all selected + * FMPI2C1 pins using FMPI2C_FASTMODEPLUS_FMPI2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining FMPI2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be disabled only by using FMPI2C_FASTMODEPLUS_FMPI2C1 parameter. + * @retval None + */ +void HAL_FMPI2CEx_DisableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_FMPI2C_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Disable fast mode plus driving capability for selected pin */ + CLEAR_BIT(SYSCFG->CFGR, (uint32_t)ConfigFastModePlus); +} +/** + * @} + */ +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#endif /* HAL_FMPI2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c new file mode 100644 index 0000000..1df2c7d --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus.c @@ -0,0 +1,2808 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpsmbus.c + * @author MCD Application Team + * @brief FMPSMBUS HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the System Management Bus (SMBus) peripheral, + * based on I2C principles of operation : + * + Initialization and de-initialization functions + * + IO operation 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 FMPSMBUS HAL driver can be used as follows: + + (#) Declare a FMPSMBUS_HandleTypeDef handle structure, for example: + FMPSMBUS_HandleTypeDef hfmpsmbus; + + (#)Initialize the FMPSMBUS low level resources by implementing the HAL_FMPSMBUS_MspInit() API: + (##) Enable the FMPSMBUSx interface clock + (##) FMPSMBUS pins configuration + (+++) Enable the clock for the FMPSMBUS GPIOs + (+++) Configure FMPSMBUS pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the FMPSMBUSx interrupt priority + (+++) Enable the NVIC FMPSMBUS IRQ Channel + + (#) Configure the Communication Clock Timing, Bus Timeout, Own Address1, Master Addressing mode, + Dual Addressing mode, Own Address2, Own Address2 Mask, General call, Nostretch mode, + Peripheral mode and Packet Error Check mode in the hfmpsmbus Init structure. + + (#) Initialize the FMPSMBUS registers by calling the HAL_FMPSMBUS_Init() API: + (++) These API's configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_FMPSMBUS_MspInit(&hfmpsmbus) API. + + (#) To check if target device is ready for communication, use the function HAL_FMPSMBUS_IsDeviceReady() + + (#) For FMPSMBUS IO operations, only one mode of operations is available within this driver + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master/host FMPSMBUS mode an amount of data in non-blocking mode + using HAL_FMPSMBUS_Master_Transmit_IT() + (++) At transmission end of transfer HAL_FMPSMBUS_MasterTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_MasterTxCpltCallback() + (+) Receive in master/host FMPSMBUS mode an amount of data in non-blocking mode + using HAL_FMPSMBUS_Master_Receive_IT() + (++) At reception end of transfer HAL_FMPSMBUS_MasterRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_MasterRxCpltCallback() + (+) Abort a master/host FMPSMBUS process communication with Interrupt using HAL_FMPSMBUS_Master_Abort_IT() + (++) The associated previous transfer callback is called at the end of abort process + (++) mean HAL_FMPSMBUS_MasterTxCpltCallback() in case of previous state was master transmit + (++) mean HAL_FMPSMBUS_MasterRxCpltCallback() in case of previous state was master receive + (+) Enable/disable the Address listen mode in slave/device or host/slave FMPSMBUS mode + using HAL_FMPSMBUS_EnableListen_IT() HAL_FMPSMBUS_DisableListen_IT() + (++) When address slave/device FMPSMBUS match, HAL_FMPSMBUS_AddrCallback() is executed and users can + add their own code to check the Address Match Code and the transmission direction + request by master/host (Write/Read). + (++) At Listen mode end HAL_FMPSMBUS_ListenCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_ListenCpltCallback() + (+) Transmit in slave/device FMPSMBUS mode an amount of data in non-blocking mode + using HAL_FMPSMBUS_Slave_Transmit_IT() + (++) At transmission end of transfer HAL_FMPSMBUS_SlaveTxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_SlaveTxCpltCallback() + (+) Receive in slave/device FMPSMBUS mode an amount of data in non-blocking mode + using HAL_FMPSMBUS_Slave_Receive_IT() + (++) At reception end of transfer HAL_FMPSMBUS_SlaveRxCpltCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_SlaveRxCpltCallback() + (+) Enable/Disable the FMPSMBUS alert mode using + HAL_FMPSMBUS_EnableAlert_IT() or HAL_FMPSMBUS_DisableAlert_IT() + (++) When FMPSMBUS Alert is generated HAL_FMPSMBUS_ErrorCallback() is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_ErrorCallback() + to check the Alert Error Code using function HAL_FMPSMBUS_GetError() + (+) Get HAL state machine or error values using HAL_FMPSMBUS_GetState() or HAL_FMPSMBUS_GetError() + (+) In case of transfer Error, HAL_FMPSMBUS_ErrorCallback() function is executed and users can + add their own code by customization of function pointer HAL_FMPSMBUS_ErrorCallback() + to check the Error Code using function HAL_FMPSMBUS_GetError() + + *** FMPSMBUS HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in FMPSMBUS HAL driver. + + (+) __HAL_FMPSMBUS_ENABLE: Enable the FMPSMBUS peripheral + (+) __HAL_FMPSMBUS_DISABLE: Disable the FMPSMBUS peripheral + (+) __HAL_FMPSMBUS_GET_FLAG: Check whether the specified FMPSMBUS flag is set or not + (+) __HAL_FMPSMBUS_CLEAR_FLAG: Clear the specified FMPSMBUS pending flag + (+) __HAL_FMPSMBUS_ENABLE_IT: Enable the specified FMPSMBUS interrupt + (+) __HAL_FMPSMBUS_DISABLE_IT: Disable the specified FMPSMBUS interrupt + + *** Callback registration *** + ============================================= + [..] + The compilation flag USE_HAL_FMPSMBUS_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_FMPSMBUS_RegisterCallback() or HAL_FMPSMBUS_RegisterAddrCallback() + to register an interrupt callback. + [..] + Function HAL_FMPSMBUS_RegisterCallback() allows to register following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + For specific callback AddrCallback use dedicated register callbacks : HAL_FMPSMBUS_RegisterAddrCallback. + [..] + Use function HAL_FMPSMBUS_UnRegisterCallback to reset a callback to the default + weak function. + HAL_FMPSMBUS_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) ErrorCallback : callback for error detection. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + [..] + For callback AddrCallback use dedicated register callbacks : HAL_FMPSMBUS_UnRegisterAddrCallback. + [..] + By default, after the HAL_FMPSMBUS_Init() and when the state is HAL_FMPI2C_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_FMPSMBUS_MasterTxCpltCallback(), HAL_FMPSMBUS_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_FMPSMBUS_Init()/ HAL_FMPSMBUS_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_FMPSMBUS_Init()/ HAL_FMPSMBUS_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + [..] + Callbacks can be registered/unregistered in HAL_FMPI2C_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_FMPI2C_STATE_READY or HAL_FMPI2C_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_FMPSMBUS_RegisterCallback() before calling HAL_FMPSMBUS_DeInit() + or HAL_FMPSMBUS_Init() function. + [..] + When the compilation flag USE_HAL_FMPSMBUS_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + [..] + (@) You can refer to the FMPSMBUS HAL driver header file for more useful macros + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup FMPSMBUS FMPSMBUS + * @brief FMPSMBUS HAL module driver + * @{ + */ + +#ifdef HAL_FMPSMBUS_MODULE_ENABLED + +#if defined(FMPI2C_CR1_PE) +/* Private typedef -----------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup FMPSMBUS_Private_Define FMPSMBUS Private Constants + * @{ + */ +#define TIMING_CLEAR_MASK (0xF0FFFFFFUL) /*!< FMPSMBUS TIMING clear register Mask */ +#define HAL_TIMEOUT_ADDR (10000U) /*!< 10 s */ +#define HAL_TIMEOUT_BUSY (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_DIR (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_RXNE (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_STOPF (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_TC (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_TCR (25U) /*!< 25 ms */ +#define HAL_TIMEOUT_TXIS (25U) /*!< 25 ms */ +#define MAX_NBYTE_SIZE 255U +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup FMPSMBUS_Private_Functions FMPSMBUS Private Functions + * @{ + */ +/* Private functions to handle flags during polling transfer */ +static HAL_StatusTypeDef FMPSMBUS_WaitOnFlagUntilTimeout(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t Flag, + FlagStatus Status, uint32_t Timeout); + +/* Private functions for FMPSMBUS transfer IRQ handler */ +static HAL_StatusTypeDef FMPSMBUS_Master_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags); +static HAL_StatusTypeDef FMPSMBUS_Slave_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags); +static void FMPSMBUS_ITErrorHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus); + +/* Private functions to centralize the enable/disable of Interrupts */ +static void FMPSMBUS_Enable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest); +static void FMPSMBUS_Disable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest); + +/* Private function to flush TXDR register */ +static void FMPSMBUS_Flush_TXDR(FMPSMBUS_HandleTypeDef *hfmpsmbus); + +/* Private function to handle start, restart or stop a transfer */ +static void FMPSMBUS_TransferConfig(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, uint8_t Size, + uint32_t Mode, uint32_t Request); + +/* Private function to Convert Specific options */ +static void FMPSMBUS_ConvertOtherXferOptions(FMPSMBUS_HandleTypeDef *hfmpsmbus); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup FMPSMBUS_Exported_Functions FMPSMBUS Exported Functions + * @{ + */ + +/** @defgroup FMPSMBUS_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the FMPSMBUSx peripheral: + + (+) User must Implement HAL_FMPSMBUS_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, IT and NVIC ). + + (+) Call the function HAL_FMPSMBUS_Init() to configure the selected device with + the selected configuration: + (++) Clock Timing + (++) Bus Timeout + (++) Analog Filer mode + (++) Own Address 1 + (++) Addressing mode (Master, Slave) + (++) Dual Addressing mode + (++) Own Address 2 + (++) Own Address 2 Mask + (++) General call mode + (++) Nostretch mode + (++) Packet Error Check mode + (++) Peripheral mode + + + (+) Call the function HAL_FMPSMBUS_DeInit() to restore the default configuration + of the selected FMPSMBUSx peripheral. + + (+) Enable/Disable Analog/Digital filters with HAL_FMPSMBUS_ConfigAnalogFilter() and + HAL_FMPSMBUS_ConfigDigitalFilter(). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the FMPSMBUS according to the specified parameters + * in the FMPSMBUS_InitTypeDef and initialize the associated handle. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Init(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Check the FMPSMBUS handle allocation */ + if (hfmpsmbus == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_FMPSMBUS_ALL_INSTANCE(hfmpsmbus->Instance)); + assert_param(IS_FMPSMBUS_ANALOG_FILTER(hfmpsmbus->Init.AnalogFilter)); + assert_param(IS_FMPSMBUS_OWN_ADDRESS1(hfmpsmbus->Init.OwnAddress1)); + assert_param(IS_FMPSMBUS_ADDRESSING_MODE(hfmpsmbus->Init.AddressingMode)); + assert_param(IS_FMPSMBUS_DUAL_ADDRESS(hfmpsmbus->Init.DualAddressMode)); + assert_param(IS_FMPSMBUS_OWN_ADDRESS2(hfmpsmbus->Init.OwnAddress2)); + assert_param(IS_FMPSMBUS_OWN_ADDRESS2_MASK(hfmpsmbus->Init.OwnAddress2Masks)); + assert_param(IS_FMPSMBUS_GENERAL_CALL(hfmpsmbus->Init.GeneralCallMode)); + assert_param(IS_FMPSMBUS_NO_STRETCH(hfmpsmbus->Init.NoStretchMode)); + assert_param(IS_FMPSMBUS_PEC(hfmpsmbus->Init.PacketErrorCheckMode)); + assert_param(IS_FMPSMBUS_PERIPHERAL_MODE(hfmpsmbus->Init.PeripheralMode)); + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hfmpsmbus->Lock = HAL_UNLOCKED; + +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterTxCpltCallback = HAL_FMPSMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + hfmpsmbus->MasterRxCpltCallback = HAL_FMPSMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + hfmpsmbus->SlaveTxCpltCallback = HAL_FMPSMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + hfmpsmbus->SlaveRxCpltCallback = HAL_FMPSMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + hfmpsmbus->ListenCpltCallback = HAL_FMPSMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + hfmpsmbus->ErrorCallback = HAL_FMPSMBUS_ErrorCallback; /* Legacy weak ErrorCallback */ + hfmpsmbus->AddrCallback = HAL_FMPSMBUS_AddrCallback; /* Legacy weak AddrCallback */ + + if (hfmpsmbus->MspInitCallback == NULL) + { + hfmpsmbus->MspInitCallback = HAL_FMPSMBUS_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + hfmpsmbus->MspInitCallback(hfmpsmbus); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_FMPSMBUS_MspInit(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_BUSY; + + /* Disable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_DISABLE(hfmpsmbus); + + /*---------------------------- FMPSMBUSx TIMINGR Configuration ------------------------*/ + /* Configure FMPSMBUSx: Frequency range */ + hfmpsmbus->Instance->TIMINGR = hfmpsmbus->Init.Timing & TIMING_CLEAR_MASK; + + /*---------------------------- FMPSMBUSx TIMEOUTR Configuration ------------------------*/ + /* Configure FMPSMBUSx: Bus Timeout */ + hfmpsmbus->Instance->TIMEOUTR &= ~FMPI2C_TIMEOUTR_TIMOUTEN; + hfmpsmbus->Instance->TIMEOUTR &= ~FMPI2C_TIMEOUTR_TEXTEN; + hfmpsmbus->Instance->TIMEOUTR = hfmpsmbus->Init.SMBusTimeout; + + /*---------------------------- FMPSMBUSx OAR1 Configuration -----------------------*/ + /* Configure FMPSMBUSx: Own Address1 and ack own address1 mode */ + hfmpsmbus->Instance->OAR1 &= ~FMPI2C_OAR1_OA1EN; + + if (hfmpsmbus->Init.OwnAddress1 != 0UL) + { + if (hfmpsmbus->Init.AddressingMode == FMPSMBUS_ADDRESSINGMODE_7BIT) + { + hfmpsmbus->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | hfmpsmbus->Init.OwnAddress1); + } + else /* FMPSMBUS_ADDRESSINGMODE_10BIT */ + { + hfmpsmbus->Instance->OAR1 = (FMPI2C_OAR1_OA1EN | FMPI2C_OAR1_OA1MODE | hfmpsmbus->Init.OwnAddress1); + } + } + + /*---------------------------- FMPSMBUSx CR2 Configuration ------------------------*/ + /* Configure FMPSMBUSx: Addressing Master mode */ + if (hfmpsmbus->Init.AddressingMode == FMPSMBUS_ADDRESSINGMODE_10BIT) + { + hfmpsmbus->Instance->CR2 = (FMPI2C_CR2_ADD10); + } + /* Enable the AUTOEND by default, and enable NACK (should be disable only during Slave process) */ + /* AUTOEND and NACK bit will be manage during Transfer process */ + hfmpsmbus->Instance->CR2 |= (FMPI2C_CR2_AUTOEND | FMPI2C_CR2_NACK); + + /*---------------------------- FMPSMBUSx OAR2 Configuration -----------------------*/ + /* Configure FMPSMBUSx: Dual mode and Own Address2 */ + hfmpsmbus->Instance->OAR2 = (hfmpsmbus->Init.DualAddressMode | hfmpsmbus->Init.OwnAddress2 | \ + (hfmpsmbus->Init.OwnAddress2Masks << 8U)); + + /*---------------------------- FMPSMBUSx CR1 Configuration ------------------------*/ + /* Configure FMPSMBUSx: Generalcall and NoStretch mode */ + hfmpsmbus->Instance->CR1 = (hfmpsmbus->Init.GeneralCallMode | hfmpsmbus->Init.NoStretchMode | \ + hfmpsmbus->Init.PacketErrorCheckMode | hfmpsmbus->Init.PeripheralMode | \ + hfmpsmbus->Init.AnalogFilter); + + /* Enable Slave Byte Control only in case of Packet Error Check is enabled + and FMPSMBUS Peripheral is set in Slave mode */ + if ((hfmpsmbus->Init.PacketErrorCheckMode == FMPSMBUS_PEC_ENABLE) && \ + ((hfmpsmbus->Init.PeripheralMode == FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE) || \ + (hfmpsmbus->Init.PeripheralMode == FMPSMBUS_PERIPHERAL_MODE_FMPSMBUS_SLAVE_ARP))) + { + hfmpsmbus->Instance->CR1 |= FMPI2C_CR1_SBC; + } + + /* Enable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_ENABLE(hfmpsmbus); + + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + hfmpsmbus->PreviousState = HAL_FMPSMBUS_STATE_READY; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitialize the FMPSMBUS peripheral. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_DeInit(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Check the FMPSMBUS handle allocation */ + if (hfmpsmbus == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_FMPSMBUS_ALL_INSTANCE(hfmpsmbus->Instance)); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_BUSY; + + /* Disable the FMPSMBUS Peripheral Clock */ + __HAL_FMPSMBUS_DISABLE(hfmpsmbus); + +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + if (hfmpsmbus->MspDeInitCallback == NULL) + { + hfmpsmbus->MspDeInitCallback = HAL_FMPSMBUS_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + hfmpsmbus->MspDeInitCallback(hfmpsmbus); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_FMPSMBUS_MspDeInit(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + hfmpsmbus->PreviousState = HAL_FMPSMBUS_STATE_RESET; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; +} + +/** + * @brief Initialize the FMPSMBUS MSP. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_MspInit(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the FMPSMBUS MSP. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_MspDeInit(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief Configure Analog noise filter. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param AnalogFilter This parameter can be one of the following values: + * @arg @ref FMPSMBUS_ANALOGFILTER_ENABLE + * @arg @ref FMPSMBUS_ANALOGFILTER_DISABLE + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_ConfigAnalogFilter(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_FMPSMBUS_ALL_INSTANCE(hfmpsmbus->Instance)); + assert_param(IS_FMPSMBUS_ANALOG_FILTER(AnalogFilter)); + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_BUSY; + + /* Disable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_DISABLE(hfmpsmbus); + + /* Reset ANOFF bit */ + hfmpsmbus->Instance->CR1 &= ~(FMPI2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + hfmpsmbus->Instance->CR1 |= AnalogFilter; + + __HAL_FMPSMBUS_ENABLE(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configure Digital noise filter. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param DigitalFilter Coefficient of digital noise filter between Min_Data=0x00 and Max_Data=0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_ConfigDigitalFilter(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t DigitalFilter) +{ + uint32_t tmpreg; + + /* Check the parameters */ + assert_param(IS_FMPSMBUS_ALL_INSTANCE(hfmpsmbus->Instance)); + assert_param(IS_FMPSMBUS_DIGITAL_FILTER(DigitalFilter)); + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_BUSY; + + /* Disable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_DISABLE(hfmpsmbus); + + /* Get the old register value */ + tmpreg = hfmpsmbus->Instance->CR1; + + /* Reset FMPI2C DNF bits [11:8] */ + tmpreg &= ~(FMPI2C_CR1_DNF); + + /* Set FMPI2Cx DNF coefficient */ + tmpreg |= DigitalFilter << FMPI2C_CR1_DNF_Pos; + + /* Store the new register value */ + hfmpsmbus->Instance->CR1 = tmpreg; + + __HAL_FMPSMBUS_ENABLE(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User FMPSMBUS Callback + * To be used instead of the weak predefined callback + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_FMPSMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_FMPSMBUS_ERROR_CB_ID Error callback ID + * @arg @ref HAL_FMPSMBUS_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_FMPSMBUS_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_RegisterCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + HAL_FMPSMBUS_CallbackIDTypeDef CallbackID, + pFMPSMBUS_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hfmpsmbus); + + if (HAL_FMPSMBUS_STATE_READY == hfmpsmbus->State) + { + switch (CallbackID) + { + case HAL_FMPSMBUS_MASTER_TX_COMPLETE_CB_ID : + hfmpsmbus->MasterTxCpltCallback = pCallback; + break; + + case HAL_FMPSMBUS_MASTER_RX_COMPLETE_CB_ID : + hfmpsmbus->MasterRxCpltCallback = pCallback; + break; + + case HAL_FMPSMBUS_SLAVE_TX_COMPLETE_CB_ID : + hfmpsmbus->SlaveTxCpltCallback = pCallback; + break; + + case HAL_FMPSMBUS_SLAVE_RX_COMPLETE_CB_ID : + hfmpsmbus->SlaveRxCpltCallback = pCallback; + break; + + case HAL_FMPSMBUS_LISTEN_COMPLETE_CB_ID : + hfmpsmbus->ListenCpltCallback = pCallback; + break; + + case HAL_FMPSMBUS_ERROR_CB_ID : + hfmpsmbus->ErrorCallback = pCallback; + break; + + case HAL_FMPSMBUS_MSPINIT_CB_ID : + hfmpsmbus->MspInitCallback = pCallback; + break; + + case HAL_FMPSMBUS_MSPDEINIT_CB_ID : + hfmpsmbus->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_FMPSMBUS_STATE_RESET == hfmpsmbus->State) + { + switch (CallbackID) + { + case HAL_FMPSMBUS_MSPINIT_CB_ID : + hfmpsmbus->MspInitCallback = pCallback; + break; + + case HAL_FMPSMBUS_MSPDEINIT_CB_ID : + hfmpsmbus->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpsmbus); + return status; +} + +/** + * @brief Unregister an FMPSMBUS Callback + * FMPSMBUS callback is redirected to the weak predefined callback + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * This parameter can be one of the following values: + * @arg @ref HAL_FMPSMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_FMPSMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_FMPSMBUS_ERROR_CB_ID Error callback ID + * @arg @ref HAL_FMPSMBUS_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_FMPSMBUS_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_UnRegisterCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + HAL_FMPSMBUS_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hfmpsmbus); + + if (HAL_FMPSMBUS_STATE_READY == hfmpsmbus->State) + { + switch (CallbackID) + { + case HAL_FMPSMBUS_MASTER_TX_COMPLETE_CB_ID : + hfmpsmbus->MasterTxCpltCallback = HAL_FMPSMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + break; + + case HAL_FMPSMBUS_MASTER_RX_COMPLETE_CB_ID : + hfmpsmbus->MasterRxCpltCallback = HAL_FMPSMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + break; + + case HAL_FMPSMBUS_SLAVE_TX_COMPLETE_CB_ID : + hfmpsmbus->SlaveTxCpltCallback = HAL_FMPSMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + break; + + case HAL_FMPSMBUS_SLAVE_RX_COMPLETE_CB_ID : + hfmpsmbus->SlaveRxCpltCallback = HAL_FMPSMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + break; + + case HAL_FMPSMBUS_LISTEN_COMPLETE_CB_ID : + hfmpsmbus->ListenCpltCallback = HAL_FMPSMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + break; + + case HAL_FMPSMBUS_ERROR_CB_ID : + hfmpsmbus->ErrorCallback = HAL_FMPSMBUS_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_FMPSMBUS_MSPINIT_CB_ID : + hfmpsmbus->MspInitCallback = HAL_FMPSMBUS_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_FMPSMBUS_MSPDEINIT_CB_ID : + hfmpsmbus->MspDeInitCallback = HAL_FMPSMBUS_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_FMPSMBUS_STATE_RESET == hfmpsmbus->State) + { + switch (CallbackID) + { + case HAL_FMPSMBUS_MSPINIT_CB_ID : + hfmpsmbus->MspInitCallback = HAL_FMPSMBUS_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_FMPSMBUS_MSPDEINIT_CB_ID : + hfmpsmbus->MspDeInitCallback = HAL_FMPSMBUS_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpsmbus); + return status; +} + +/** + * @brief Register the Slave Address Match FMPSMBUS Callback + * To be used instead of the weak HAL_FMPSMBUS_AddrCallback() predefined callback + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param pCallback pointer to the Address Match Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_RegisterAddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, + pFMPSMBUS_AddrCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hfmpsmbus); + + if (HAL_FMPSMBUS_STATE_READY == hfmpsmbus->State) + { + hfmpsmbus->AddrCallback = pCallback; + } + else + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpsmbus); + return status; +} + +/** + * @brief UnRegister the Slave Address Match FMPSMBUS Callback + * Info Ready FMPSMBUS Callback is redirected to the weak HAL_FMPSMBUS_AddrCallback() predefined callback + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_UnRegisterAddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hfmpsmbus); + + if (HAL_FMPSMBUS_STATE_READY == hfmpsmbus->State) + { + hfmpsmbus->AddrCallback = HAL_FMPSMBUS_AddrCallback; /* Legacy weak AddrCallback */ + } + else + { + /* Update the error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hfmpsmbus); + return status; +} + +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup FMPSMBUS_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the FMPSMBUS data + transfers. + + (#) Blocking mode function to check if device is ready for usage is : + (++) HAL_FMPSMBUS_IsDeviceReady() + + (#) There is only one mode of transfer: + (++) Non-Blocking mode : The communication is performed using Interrupts. + These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated FMPSMBUS IRQ when using Interrupt mode. + + (#) Non-Blocking mode functions with Interrupt are : + (++) HAL_FMPSMBUS_Master_Transmit_IT() + (++) HAL_FMPSMBUS_Master_Receive_IT() + (++) HAL_FMPSMBUS_Slave_Transmit_IT() + (++) HAL_FMPSMBUS_Slave_Receive_IT() + (++) HAL_FMPSMBUS_EnableListen_IT() or alias HAL_FMPSMBUS_EnableListen_IT() + (++) HAL_FMPSMBUS_DisableListen_IT() + (++) HAL_FMPSMBUS_EnableAlert_IT() + (++) HAL_FMPSMBUS_DisableAlert_IT() + + (#) A set of Transfer Complete Callbacks are provided in non-Blocking mode: + (++) HAL_FMPSMBUS_MasterTxCpltCallback() + (++) HAL_FMPSMBUS_MasterRxCpltCallback() + (++) HAL_FMPSMBUS_SlaveTxCpltCallback() + (++) HAL_FMPSMBUS_SlaveRxCpltCallback() + (++) HAL_FMPSMBUS_AddrCallback() + (++) HAL_FMPSMBUS_ListenCpltCallback() + (++) HAL_FMPSMBUS_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmit in master/host FMPSMBUS mode an amount of data in non-blocking mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPSMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Transmit_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, + uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t tmp; + uint32_t sizetoxfer = 0U; + + /* Check the parameters */ + assert_param(IS_FMPSMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_MASTER_BUSY_TX; + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + /* Prepare transfer parameters */ + hfmpsmbus->pBuffPtr = pData; + hfmpsmbus->XferCount = Size; + hfmpsmbus->XferOptions = XferOptions; + + /* In case of Quick command, remove autoend mode */ + /* Manage the stop generation by software */ + if (hfmpsmbus->pBuffPtr == NULL) + { + hfmpsmbus->XferOptions &= ~FMPSMBUS_AUTOEND_MODE; + } + + if (Size > MAX_NBYTE_SIZE) + { + hfmpsmbus->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpsmbus->XferSize = Size; + } + + sizetoxfer = hfmpsmbus->XferSize; + if ((hfmpsmbus->XferSize > 0U) && ((XferOptions == FMPSMBUS_FIRST_FRAME) || + (XferOptions == FMPSMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || + (XferOptions == FMPSMBUS_FIRST_FRAME_WITH_PEC) || + (XferOptions == FMPSMBUS_FIRST_AND_LAST_FRAME_WITH_PEC))) + { + /* Preload TX register */ + /* Write data to TXDR */ + hfmpsmbus->Instance->TXDR = *hfmpsmbus->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + hfmpsmbus->XferCount--; + hfmpsmbus->XferSize--; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */ + if ((sizetoxfer < hfmpsmbus->XferCount) && (sizetoxfer == MAX_NBYTE_SIZE)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)sizetoxfer, + FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE), + FMPSMBUS_GENERATE_START_WRITE); + } + else + { + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + + /* Store current volatile XferOptions, misra rule */ + tmp = hfmpsmbus->XferOptions; + + if ((hfmpsmbus->PreviousState == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) && \ + (IS_FMPSMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)sizetoxfer, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + } + /* Else transfer direction change, so generate Restart with new transfer direction */ + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPSMBUS_ConvertOtherXferOptions(hfmpsmbus); + + /* Handle Transfer */ + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)sizetoxfer, + hfmpsmbus->XferOptions, + FMPSMBUS_GENERATE_START_WRITE); + } + + /* If PEC mode is enable, size to transmit manage by SW part should be Size-1 byte, corresponding to PEC byte */ + /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */ + if (FMPSMBUS_GET_PEC_MODE(hfmpsmbus) != 0UL) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Note : The FMPSMBUS interrupts must be enabled after unlocking current process + to avoid the risk of FMPSMBUS interrupt handle execution before current + process unlock */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master/host FMPSMBUS mode an amount of data in non-blocking mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPSMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Receive_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, uint8_t *pData, + uint16_t Size, uint32_t XferOptions) +{ + uint32_t tmp; + + /* Check the parameters */ + assert_param(IS_FMPSMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_MASTER_BUSY_RX; + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + + /* Prepare transfer parameters */ + hfmpsmbus->pBuffPtr = pData; + hfmpsmbus->XferCount = Size; + hfmpsmbus->XferOptions = XferOptions; + + /* In case of Quick command, remove autoend mode */ + /* Manage the stop generation by software */ + if (hfmpsmbus->pBuffPtr == NULL) + { + hfmpsmbus->XferOptions &= ~FMPSMBUS_AUTOEND_MODE; + } + + if (Size > MAX_NBYTE_SIZE) + { + hfmpsmbus->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpsmbus->XferSize = Size; + } + + /* Send Slave Address */ + /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */ + if ((hfmpsmbus->XferSize < hfmpsmbus->XferCount) && (hfmpsmbus->XferSize == MAX_NBYTE_SIZE)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)hfmpsmbus->XferSize, + FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE), + FMPSMBUS_GENERATE_START_READ); + } + else + { + /* If transfer direction not change, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + + /* Store current volatile XferOptions, Misra rule */ + tmp = hfmpsmbus->XferOptions; + + if ((hfmpsmbus->PreviousState == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) && \ + (IS_FMPSMBUS_TRANSFER_OTHER_OPTIONS_REQUEST(tmp) == 0)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)hfmpsmbus->XferSize, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + } + /* Else transfer direction change, so generate Restart with new transfer direction */ + else + { + /* Convert OTHER_xxx XferOptions if any */ + FMPSMBUS_ConvertOtherXferOptions(hfmpsmbus); + + /* Handle Transfer */ + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)hfmpsmbus->XferSize, + hfmpsmbus->XferOptions, + FMPSMBUS_GENERATE_START_READ); + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Note : The FMPSMBUS interrupts must be enabled after unlocking current process + to avoid the risk of FMPSMBUS interrupt handle execution before current + process unlock */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master/host FMPSMBUS process communication with Interrupt. + * @note This abort can be called only if state is ready + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Master_Abort_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress) +{ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + /* Keep the same state as previous */ + /* to perform as well the call of the corresponding end of transfer callback */ + if (hfmpsmbus->PreviousState == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + hfmpsmbus->State = HAL_FMPSMBUS_STATE_MASTER_BUSY_TX; + } + else if (hfmpsmbus->PreviousState == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + hfmpsmbus->State = HAL_FMPSMBUS_STATE_MASTER_BUSY_RX; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + return HAL_ERROR; + } + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + + /* Set NBYTES to 1 to generate a dummy read on FMPSMBUS peripheral */ + /* Set AUTOEND mode, this will generate a NACK then STOP condition to abort the current transfer */ + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, 1, FMPSMBUS_AUTOEND_MODE, FMPSMBUS_NO_STARTSTOP); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Note : The FMPSMBUS interrupts must be enabled after unlocking current process + to avoid the risk of FMPSMBUS interrupt handle execution before current + process unlock */ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + } + else if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + } + else + { + /* Nothing to do */ + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave/device FMPSMBUS mode an amount of data in non-blocking mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPSMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Slave_Transmit_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_FMPSMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_LISTEN) == HAL_FMPSMBUS_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0UL)) + { + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_ADDR | FMPSMBUS_IT_TX); + + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = (HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX | HAL_FMPSMBUS_STATE_LISTEN); + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + + /* Set SBC bit to manage Acknowledge at each bit */ + hfmpsmbus->Instance->CR1 |= FMPI2C_CR1_SBC; + + /* Enable Address Acknowledge */ + hfmpsmbus->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpsmbus->pBuffPtr = pData; + hfmpsmbus->XferCount = Size; + hfmpsmbus->XferOptions = XferOptions; + + /* Convert OTHER_xxx XferOptions if any */ + FMPSMBUS_ConvertOtherXferOptions(hfmpsmbus); + + if (Size > MAX_NBYTE_SIZE) + { + hfmpsmbus->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpsmbus->XferSize = Size; + } + + /* Set NBYTES to write and reload if size > MAX_NBYTE_SIZE and generate RESTART */ + if ((hfmpsmbus->XferSize < hfmpsmbus->XferCount) && (hfmpsmbus->XferSize == MAX_NBYTE_SIZE)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, 0, (uint8_t)hfmpsmbus->XferSize, + FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE), + FMPSMBUS_NO_STARTSTOP); + } + else + { + /* Set NBYTE to transmit */ + FMPSMBUS_TransferConfig(hfmpsmbus, 0, (uint8_t)hfmpsmbus->XferSize, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + + /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */ + /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */ + if (FMPSMBUS_GET_PEC_MODE(hfmpsmbus) != 0UL) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the HOST */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Note : The FMPSMBUS interrupts must be enabled after unlocking current process + to avoid the risk of FMPSMBUS interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX | FMPSMBUS_IT_ADDR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave/device FMPSMBUS mode an amount of data in non-blocking mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref FMPSMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_Slave_Receive_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t *pData, uint16_t Size, + uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_FMPSMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_LISTEN) == HAL_FMPSMBUS_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0UL)) + { + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_INVALID_PARAM; + return HAL_ERROR; + } + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_ADDR | FMPSMBUS_IT_RX); + + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = (HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX | HAL_FMPSMBUS_STATE_LISTEN); + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + + /* Set SBC bit to manage Acknowledge at each bit */ + hfmpsmbus->Instance->CR1 |= FMPI2C_CR1_SBC; + + /* Enable Address Acknowledge */ + hfmpsmbus->Instance->CR2 &= ~FMPI2C_CR2_NACK; + + /* Prepare transfer parameters */ + hfmpsmbus->pBuffPtr = pData; + hfmpsmbus->XferSize = Size; + hfmpsmbus->XferCount = Size; + hfmpsmbus->XferOptions = XferOptions; + + /* Convert OTHER_xxx XferOptions if any */ + FMPSMBUS_ConvertOtherXferOptions(hfmpsmbus); + + /* Set NBYTE to receive */ + /* If XferSize equal "1", or XferSize equal "2" with PEC requested (mean 1 data byte + 1 PEC byte */ + /* no need to set RELOAD bit mode, a ACK will be automatically generated in that case */ + /* else need to set RELOAD bit mode to generate an automatic ACK at each byte Received */ + /* This RELOAD bit will be reset for last BYTE to be receive in FMPSMBUS_Slave_ISR */ + if (((FMPSMBUS_GET_PEC_MODE(hfmpsmbus) != 0UL) && (hfmpsmbus->XferSize == 2U)) || (hfmpsmbus->XferSize == 1U)) + { + FMPSMBUS_TransferConfig(hfmpsmbus, 0, (uint8_t)hfmpsmbus->XferSize, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + } + else + { + FMPSMBUS_TransferConfig(hfmpsmbus, 0, 1, hfmpsmbus->XferOptions | FMPSMBUS_RELOAD_MODE, FMPSMBUS_NO_STARTSTOP); + } + + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the HOST */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ADDR); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Note : The FMPSMBUS interrupts must be enabled after unlocking current process + to avoid the risk of FMPSMBUS interrupt handle execution before current + process unlock */ + /* REnable ADDR interrupt */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX | FMPSMBUS_IT_ADDR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_EnableListen_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + hfmpsmbus->State = HAL_FMPSMBUS_STATE_LISTEN; + + /* Enable the Address Match interrupt */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_ADDR); + + return HAL_OK; +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_DisableListen_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_LISTEN) + { + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Disable the Address Match interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_ADDR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the FMPSMBUS alert mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUSx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_EnableAlert_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Enable SMBus alert */ + hfmpsmbus->Instance->CR1 |= FMPI2C_CR1_ALERTEN; + + /* Clear ALERT flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ALERT); + + /* Enable Alert Interrupt */ + FMPSMBUS_Enable_IRQ(hfmpsmbus, FMPSMBUS_IT_ALERT); + + return HAL_OK; +} +/** + * @brief Disable the FMPSMBUS alert mode with Interrupt. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUSx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_DisableAlert_IT(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Enable SMBus alert */ + hfmpsmbus->Instance->CR1 &= ~FMPI2C_CR1_ALERTEN; + + /* Disable Alert Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_ALERT); + + return HAL_OK; +} + +/** + * @brief Check if target device is ready for communication. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_FMPSMBUS_IsDeviceReady(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, uint32_t Trials, + uint32_t Timeout) +{ + uint32_t tickstart; + + __IO uint32_t FMPSMBUS_Trials = 0UL; + + FlagStatus tmp1; + FlagStatus tmp2; + + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_READY) + { + if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_BUSY) != RESET) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_BUSY; + hfmpsmbus->ErrorCode = HAL_FMPSMBUS_ERROR_NONE; + + do + { + /* Generate Start */ + hfmpsmbus->Instance->CR2 = FMPSMBUS_GENERATE_START(hfmpsmbus->Init.AddressingMode, DevAddress); + + /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ + /* Wait until STOPF flag is set or a NACK flag is set*/ + tickstart = HAL_GetTick(); + + tmp1 = __HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + tmp2 = __HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + + while ((tmp1 == RESET) && (tmp2 == RESET)) + { + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL)) + { + /* Device is ready */ + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Update FMPSMBUS error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_HALTIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + return HAL_ERROR; + } + } + + tmp1 = __HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + tmp2 = __HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + } + + /* Check if the NACKF flag has not been set */ + if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF) == RESET) + { + /* Wait until STOPF flag is reset */ + if (FMPSMBUS_WaitOnFlagUntilTimeout(hfmpsmbus, FMPSMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + + /* Device is ready */ + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; + } + else + { + /* Wait until STOPF flag is reset */ + if (FMPSMBUS_WaitOnFlagUntilTimeout(hfmpsmbus, FMPSMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear NACK Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + + /* Clear STOP Flag, auto generated with autoend*/ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + } + + /* Check if the maximum allowed number of trials has been reached */ + if (FMPSMBUS_Trials == Trials) + { + /* Generate Stop */ + hfmpsmbus->Instance->CR2 |= FMPI2C_CR2_STOP; + + /* Wait until STOPF flag is reset */ + if (FMPSMBUS_WaitOnFlagUntilTimeout(hfmpsmbus, FMPSMBUS_FLAG_STOPF, RESET, Timeout) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear STOP Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + } + + /* Increment Trials */ + FMPSMBUS_Trials++; + } while (FMPSMBUS_Trials < Trials); + + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Update FMPSMBUS error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_HALTIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_ERROR; + } + else + { + return HAL_BUSY; + } +} +/** + * @} + */ + +/** @defgroup FMPSMBUS_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ + +/** + * @brief Handle FMPSMBUS event interrupt request. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +void HAL_FMPSMBUS_EV_IRQHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Use a local variable to store the current ISR flags */ + /* This action will avoid a wrong treatment due to ISR flags change during interrupt handler */ + uint32_t tmpisrvalue = READ_REG(hfmpsmbus->Instance->ISR); + uint32_t tmpcr1value = READ_REG(hfmpsmbus->Instance->CR1); + + /* FMPSMBUS in mode Transmitter ---------------------------------------------------*/ + if ((FMPSMBUS_CHECK_IT_SOURCE(tmpcr1value, (FMPSMBUS_IT_TCI | FMPSMBUS_IT_STOPI | + FMPSMBUS_IT_NACKI | FMPSMBUS_IT_TXI)) != RESET) && + ((FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_TXIS) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_TCR) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_TC) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_STOPF) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_AF) != RESET))) + { + /* Slave mode selected */ + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) + { + (void)FMPSMBUS_Slave_ISR(hfmpsmbus, tmpisrvalue); + } + /* Master mode selected */ + else if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + (void)FMPSMBUS_Master_ISR(hfmpsmbus, tmpisrvalue); + } + else + { + /* Nothing to do */ + } + } + + /* FMPSMBUS in mode Receiver ----------------------------------------------------*/ + if ((FMPSMBUS_CHECK_IT_SOURCE(tmpcr1value, (FMPSMBUS_IT_TCI | FMPSMBUS_IT_STOPI | + FMPSMBUS_IT_NACKI | FMPSMBUS_IT_RXI)) != RESET) && + ((FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_RXNE) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_TCR) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_TC) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_STOPF) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_AF) != RESET))) + { + /* Slave mode selected */ + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX) + { + (void)FMPSMBUS_Slave_ISR(hfmpsmbus, tmpisrvalue); + } + /* Master mode selected */ + else if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + (void)FMPSMBUS_Master_ISR(hfmpsmbus, tmpisrvalue); + } + else + { + /* Nothing to do */ + } + } + + /* FMPSMBUS in mode Listener Only --------------------------------------------------*/ + if (((FMPSMBUS_CHECK_IT_SOURCE(tmpcr1value, FMPSMBUS_IT_ADDRI) != RESET) || + (FMPSMBUS_CHECK_IT_SOURCE(tmpcr1value, FMPSMBUS_IT_STOPI) != RESET) || + (FMPSMBUS_CHECK_IT_SOURCE(tmpcr1value, FMPSMBUS_IT_NACKI) != RESET)) && + ((FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_ADDR) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_STOPF) != RESET) || + (FMPSMBUS_CHECK_FLAG(tmpisrvalue, FMPSMBUS_FLAG_AF) != RESET))) + { + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_LISTEN) == HAL_FMPSMBUS_STATE_LISTEN) + { + (void)FMPSMBUS_Slave_ISR(hfmpsmbus, tmpisrvalue); + } + } +} + +/** + * @brief Handle FMPSMBUS error interrupt request. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +void HAL_FMPSMBUS_ER_IRQHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + FMPSMBUS_ITErrorHandler(hfmpsmbus); +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_MasterTxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_MasterTxCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_MasterRxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_MasterRxCpltCallback() could be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_SlaveTxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_SlaveTxCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_SlaveRxCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_SlaveRxCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param TransferDirection Master request Transfer Direction (Write/Read) + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_FMPSMBUS_AddrCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint8_t TransferDirection, + uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_AddrCallback() could be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_ListenCpltCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_ListenCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief FMPSMBUS error callback. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval None + */ +__weak void HAL_FMPSMBUS_ErrorCallback(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hfmpsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_FMPSMBUS_ErrorCallback() could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup FMPSMBUS_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the FMPSMBUS handle state. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval HAL state + */ +uint32_t HAL_FMPSMBUS_GetState(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* Return FMPSMBUS handle state */ + return hfmpsmbus->State; +} + +/** + * @brief Return the FMPSMBUS error code. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @retval FMPSMBUS Error Code + */ +uint32_t HAL_FMPSMBUS_GetError(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + return hfmpsmbus->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup FMPSMBUS_Private_Functions FMPSMBUS Private Functions + * @brief Data transfers Private functions + * @{ + */ + +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Master Mode. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param StatusFlags Value of Interrupt Flags. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPSMBUS_Master_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags) +{ + uint16_t DevAddress; + + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_AF) != RESET) + { + /* Clear NACK Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + + /* Set corresponding Error Code */ + /* No need to generate STOP, it is automatically done */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ACKF; + + /* Flush TX register */ + FMPSMBUS_Flush_TXDR(hfmpsmbus); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the Error callback to inform upper layer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->ErrorCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_ErrorCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_STOPF) != RESET) + { + /* Check and treat errors if errors occurs during STOP process */ + FMPSMBUS_ITErrorHandler(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + /* Disable Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + + /* Clear STOP Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPSMBUS_RESET_CR2(hfmpsmbus); + + /* Flush remaining data in Fifo register in case of error occurs before TXEmpty */ + /* Disable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_DISABLE(hfmpsmbus); + + hfmpsmbus->PreviousState = HAL_FMPSMBUS_STATE_READY; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Re-enable the selected FMPSMBUS peripheral */ + __HAL_FMPSMBUS_ENABLE(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterTxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterTxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + /* Store Last receive data if any */ + if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_RXNE) != RESET) + { + /* Read data from RXDR */ + *hfmpsmbus->pBuffPtr = (uint8_t)(hfmpsmbus->Instance->RXDR); + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + if ((hfmpsmbus->XferSize > 0U)) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + + /* Disable Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + + /* Clear STOP Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + + /* Clear Configuration Register 2 */ + FMPSMBUS_RESET_CR2(hfmpsmbus); + + hfmpsmbus->PreviousState = HAL_FMPSMBUS_STATE_READY; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterRxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterRxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_RXNE) != RESET) + { + /* Read data from RXDR */ + *hfmpsmbus->pBuffPtr = (uint8_t)(hfmpsmbus->Instance->RXDR); + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + /* Increment Size counter */ + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_TXIS) != RESET) + { + /* Write data to TXDR */ + hfmpsmbus->Instance->TXDR = *hfmpsmbus->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + /* Increment Size counter */ + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_TCR) != RESET) + { + if ((hfmpsmbus->XferCount != 0U) && (hfmpsmbus->XferSize == 0U)) + { + DevAddress = (uint16_t)(hfmpsmbus->Instance->CR2 & FMPI2C_CR2_SADD); + + if (hfmpsmbus->XferCount > MAX_NBYTE_SIZE) + { + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, MAX_NBYTE_SIZE, + (FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE)), + FMPSMBUS_NO_STARTSTOP); + hfmpsmbus->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpsmbus->XferSize = hfmpsmbus->XferCount; + FMPSMBUS_TransferConfig(hfmpsmbus, DevAddress, (uint8_t)hfmpsmbus->XferSize, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */ + /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */ + if (FMPSMBUS_GET_PEC_MODE(hfmpsmbus) != 0UL) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + } + else if ((hfmpsmbus->XferCount == 0U) && (hfmpsmbus->XferSize == 0U)) + { + /* Call TxCpltCallback() if no stop mode is set */ + if (FMPSMBUS_GET_STOP_MODE(hfmpsmbus) != FMPSMBUS_AUTOEND_MODE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + /* Disable Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterTxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterTxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterRxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterRxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } + } + else + { + /* Nothing to do */ + } + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_TC) != RESET) + { + if (hfmpsmbus->XferCount == 0U) + { + /* Specific use case for Quick command */ + if (hfmpsmbus->pBuffPtr == NULL) + { + /* Generate a Stop command */ + hfmpsmbus->Instance->CR2 |= FMPI2C_CR2_STOP; + } + /* Call TxCpltCallback() if no stop mode is set */ + else if (FMPSMBUS_GET_STOP_MODE(hfmpsmbus) != FMPSMBUS_AUTOEND_MODE) + { + /* No Generate Stop, to permit restart mode */ + /* The stop will be done at the end of transfer, when FMPSMBUS_AUTOEND_MODE enable */ + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_TX) + { + /* Disable Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterTxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterTxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else if (hfmpsmbus->State == HAL_FMPSMBUS_STATE_MASTER_BUSY_RX) + { + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->MasterRxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_MasterRxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } + else + { + /* Nothing to do */ + } + } + } + else + { + /* Nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; +} +/** + * @brief Interrupt Sub-Routine which handle the Interrupt Flags Slave Mode. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param StatusFlags Value of Interrupt Flags. + * @retval HAL status + */ +static HAL_StatusTypeDef FMPSMBUS_Slave_ISR(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t StatusFlags) +{ + uint8_t TransferDirection; + uint16_t SlaveAddrCode; + + /* Process Locked */ + __HAL_LOCK(hfmpsmbus); + + if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_AF) != RESET) + { + /* Check that FMPSMBUS transfer finished */ + /* if yes, normal usecase, a NACK is sent by the HOST when Transfer is finished */ + /* Mean XferCount == 0*/ + /* So clear Flag NACKF only */ + if (hfmpsmbus->XferCount == 0U) + { + /* Clear NACK Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + + /* Flush TX register */ + FMPSMBUS_Flush_TXDR(hfmpsmbus); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + } + else + { + /* if no, error usecase, a Non-Acknowledge of last Data is generated by the HOST*/ + /* Clear NACK Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_AF); + + /* Set HAL State to "Idle" State, mean to LISTEN state */ + /* So reset Slave Busy state */ + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State &= ~((uint32_t)HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX); + hfmpsmbus->State &= ~((uint32_t)HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX); + + /* Disable RX/TX Interrupts, keep only ADDR Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX | FMPSMBUS_IT_TX); + + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ACKF; + + /* Flush TX register */ + FMPSMBUS_Flush_TXDR(hfmpsmbus); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the Error callback to inform upper layer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->ErrorCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_ErrorCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_ADDR) != RESET) + { + TransferDirection = (uint8_t)(FMPSMBUS_GET_DIR(hfmpsmbus)); + SlaveAddrCode = (uint16_t)(FMPSMBUS_GET_ADDR_MATCH(hfmpsmbus)); + + /* Disable ADDR interrupt to prevent multiple ADDRInterrupt*/ + /* Other ADDRInterrupt will be treat in next Listen usecase */ + __HAL_FMPSMBUS_DISABLE_IT(hfmpsmbus, FMPSMBUS_IT_ADDRI); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call Slave Addr callback */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->AddrCallback(hfmpsmbus, TransferDirection, SlaveAddrCode); +#else + HAL_FMPSMBUS_AddrCallback(hfmpsmbus, TransferDirection, SlaveAddrCode); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else if ((FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_RXNE) != RESET) || + (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_TCR) != RESET)) + { + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX) + { + /* Read data from RXDR */ + *hfmpsmbus->pBuffPtr = (uint8_t)(hfmpsmbus->Instance->RXDR); + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + + if (hfmpsmbus->XferCount == 1U) + { + /* Receive last Byte, can be PEC byte in case of PEC BYTE enabled */ + /* or only the last Byte of Transfer */ + /* So reset the RELOAD bit mode */ + hfmpsmbus->XferOptions &= ~FMPSMBUS_RELOAD_MODE; + FMPSMBUS_TransferConfig(hfmpsmbus, 0, 1, hfmpsmbus->XferOptions, FMPSMBUS_NO_STARTSTOP); + } + else if (hfmpsmbus->XferCount == 0U) + { + /* Last Byte is received, disable Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX); + + /* Remove HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX, keep only HAL_FMPSMBUS_STATE_LISTEN */ + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State &= ~((uint32_t)HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->SlaveRxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_SlaveRxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Set Reload for next Bytes */ + FMPSMBUS_TransferConfig(hfmpsmbus, 0, 1, + FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE), + FMPSMBUS_NO_STARTSTOP); + + /* Ack last Byte Read */ + hfmpsmbus->Instance->CR2 &= ~FMPI2C_CR2_NACK; + } + } + else if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) + { + if ((hfmpsmbus->XferCount != 0U) && (hfmpsmbus->XferSize == 0U)) + { + if (hfmpsmbus->XferCount > MAX_NBYTE_SIZE) + { + FMPSMBUS_TransferConfig(hfmpsmbus, 0, MAX_NBYTE_SIZE, + (FMPSMBUS_RELOAD_MODE | (hfmpsmbus->XferOptions & FMPSMBUS_SENDPEC_MODE)), + FMPSMBUS_NO_STARTSTOP); + hfmpsmbus->XferSize = MAX_NBYTE_SIZE; + } + else + { + hfmpsmbus->XferSize = hfmpsmbus->XferCount; + FMPSMBUS_TransferConfig(hfmpsmbus, 0, (uint8_t)hfmpsmbus->XferSize, hfmpsmbus->XferOptions, + FMPSMBUS_NO_STARTSTOP); + /* If PEC mode is enable, size to transmit should be Size-1 byte, corresponding to PEC byte */ + /* PEC byte is automatically sent by HW block, no need to manage it in Transmit process */ + if (FMPSMBUS_GET_PEC_MODE(hfmpsmbus) != 0UL) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + } + } + else + { + /* Nothing to do */ + } + } + else if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_TXIS) != RESET) + { + /* Write data to TXDR only if XferCount not reach "0" */ + /* A TXIS flag can be set, during STOP treatment */ + /* Check if all Data have already been sent */ + /* If it is the case, this last write in TXDR is not sent, correspond to a dummy TXIS event */ + if (hfmpsmbus->XferCount > 0U) + { + /* Write data to TXDR */ + hfmpsmbus->Instance->TXDR = *hfmpsmbus->pBuffPtr; + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + hfmpsmbus->XferCount--; + hfmpsmbus->XferSize--; + } + + if (hfmpsmbus->XferCount == 0U) + { + /* Last Byte is Transmitted */ + /* Remove HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX, keep only HAL_FMPSMBUS_STATE_LISTEN */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_TX); + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State &= ~((uint32_t)HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX); + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->SlaveTxCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_SlaveTxCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + } + else + { + /* Nothing to do */ + } + + /* Check if STOPF is set */ + if (FMPSMBUS_CHECK_FLAG(StatusFlags, FMPSMBUS_FLAG_STOPF) != RESET) + { + if ((hfmpsmbus->State & HAL_FMPSMBUS_STATE_LISTEN) == HAL_FMPSMBUS_STATE_LISTEN) + { + /* Store Last receive data if any */ + if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_RXNE) != RESET) + { + /* Read data from RXDR */ + *hfmpsmbus->pBuffPtr = (uint8_t)(hfmpsmbus->Instance->RXDR); + + /* Increment Buffer pointer */ + hfmpsmbus->pBuffPtr++; + + if ((hfmpsmbus->XferSize > 0U)) + { + hfmpsmbus->XferSize--; + hfmpsmbus->XferCount--; + } + } + + /* Disable RX and TX Interrupts */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_RX | FMPSMBUS_IT_TX); + + /* Disable ADDR Interrupt */ + FMPSMBUS_Disable_IRQ(hfmpsmbus, FMPSMBUS_IT_ADDR); + + /* Disable Address Acknowledge */ + hfmpsmbus->Instance->CR2 |= FMPI2C_CR2_NACK; + + /* Clear Configuration Register 2 */ + FMPSMBUS_RESET_CR2(hfmpsmbus); + + /* Clear STOP Flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_STOPF); + + /* Clear ADDR flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ADDR); + + hfmpsmbus->XferOptions = 0; + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->ListenCpltCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_ListenCpltCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } + } + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_OK; +} +/** + * @brief Manage the enabling of Interrupts. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param InterruptRequest Value of @ref FMPSMBUS_Interrupt_configuration_definition. + * @retval HAL status + */ +static void FMPSMBUS_Enable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest) +{ + uint32_t tmpisr = 0UL; + + if ((InterruptRequest & FMPSMBUS_IT_ALERT) == FMPSMBUS_IT_ALERT) + { + /* Enable ERR interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI; + } + + if ((InterruptRequest & FMPSMBUS_IT_ADDR) == FMPSMBUS_IT_ADDR) + { + /* Enable ADDR, STOP interrupt */ + tmpisr |= FMPSMBUS_IT_ADDRI | FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI | FMPSMBUS_IT_ERRI; + } + + if ((InterruptRequest & FMPSMBUS_IT_TX) == FMPSMBUS_IT_TX) + { + /* Enable ERR, TC, STOP, NACK, RXI interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI | FMPSMBUS_IT_TCI | FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI | FMPSMBUS_IT_TXI; + } + + if ((InterruptRequest & FMPSMBUS_IT_RX) == FMPSMBUS_IT_RX) + { + /* Enable ERR, TC, STOP, NACK, TXI interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI | FMPSMBUS_IT_TCI | FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI | FMPSMBUS_IT_RXI; + } + + /* Enable interrupts only at the end */ + /* to avoid the risk of FMPSMBUS interrupt handle execution before */ + /* all interrupts requested done */ + __HAL_FMPSMBUS_ENABLE_IT(hfmpsmbus, tmpisr); +} +/** + * @brief Manage the disabling of Interrupts. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param InterruptRequest Value of @ref FMPSMBUS_Interrupt_configuration_definition. + * @retval HAL status + */ +static void FMPSMBUS_Disable_IRQ(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t InterruptRequest) +{ + uint32_t tmpisr = 0UL; + uint32_t tmpstate = hfmpsmbus->State; + + if ((tmpstate == HAL_FMPSMBUS_STATE_READY) && ((InterruptRequest & FMPSMBUS_IT_ALERT) == FMPSMBUS_IT_ALERT)) + { + /* Disable ERR interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI; + } + + if ((InterruptRequest & FMPSMBUS_IT_TX) == FMPSMBUS_IT_TX) + { + /* Disable TC, STOP, NACK and TXI interrupt */ + tmpisr |= FMPSMBUS_IT_TCI | FMPSMBUS_IT_TXI; + + if ((FMPSMBUS_GET_ALERT_ENABLED(hfmpsmbus) == 0UL) + && ((tmpstate & HAL_FMPSMBUS_STATE_LISTEN) != HAL_FMPSMBUS_STATE_LISTEN)) + { + /* Disable ERR interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI; + } + + if ((tmpstate & HAL_FMPSMBUS_STATE_LISTEN) != HAL_FMPSMBUS_STATE_LISTEN) + { + /* Disable STOP and NACK interrupt */ + tmpisr |= FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI; + } + } + + if ((InterruptRequest & FMPSMBUS_IT_RX) == FMPSMBUS_IT_RX) + { + /* Disable TC, STOP, NACK and RXI interrupt */ + tmpisr |= FMPSMBUS_IT_TCI | FMPSMBUS_IT_RXI; + + if ((FMPSMBUS_GET_ALERT_ENABLED(hfmpsmbus) == 0UL) + && ((tmpstate & HAL_FMPSMBUS_STATE_LISTEN) != HAL_FMPSMBUS_STATE_LISTEN)) + { + /* Disable ERR interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI; + } + + if ((tmpstate & HAL_FMPSMBUS_STATE_LISTEN) != HAL_FMPSMBUS_STATE_LISTEN) + { + /* Disable STOP and NACK interrupt */ + tmpisr |= FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI; + } + } + + if ((InterruptRequest & FMPSMBUS_IT_ADDR) == FMPSMBUS_IT_ADDR) + { + /* Disable ADDR, STOP and NACK interrupt */ + tmpisr |= FMPSMBUS_IT_ADDRI | FMPSMBUS_IT_STOPI | FMPSMBUS_IT_NACKI; + + if (FMPSMBUS_GET_ALERT_ENABLED(hfmpsmbus) == 0UL) + { + /* Disable ERR interrupt */ + tmpisr |= FMPSMBUS_IT_ERRI; + } + } + + /* Disable interrupts only at the end */ + /* to avoid a breaking situation like at "t" time */ + /* all disable interrupts request are not done */ + __HAL_FMPSMBUS_DISABLE_IT(hfmpsmbus, tmpisr); +} + +/** + * @brief FMPSMBUS interrupts error handler. + * @param hfmpsmbus FMPSMBUS handle. + * @retval None + */ +static void FMPSMBUS_ITErrorHandler(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + uint32_t itflags = READ_REG(hfmpsmbus->Instance->ISR); + uint32_t itsources = READ_REG(hfmpsmbus->Instance->CR1); + uint32_t tmpstate; + uint32_t tmperror; + + /* FMPSMBUS Bus error interrupt occurred ------------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_BERR) == FMPSMBUS_FLAG_BERR) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_BERR); + } + + /* FMPSMBUS Over-Run/Under-Run interrupt occurred ----------------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_OVR) == FMPSMBUS_FLAG_OVR) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_OVR); + } + + /* FMPSMBUS Arbitration Loss error interrupt occurred ------------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_ARLO) == FMPSMBUS_FLAG_ARLO) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ARLO); + } + + /* FMPSMBUS Timeout error interrupt occurred ---------------------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_TIMEOUT) == FMPSMBUS_FLAG_TIMEOUT) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_BUSTIMEOUT; + + /* Clear TIMEOUT flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TIMEOUT); + } + + /* FMPSMBUS Alert error interrupt occurred -----------------------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_ALERT) == FMPSMBUS_FLAG_ALERT) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_ALERT; + + /* Clear ALERT flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_ALERT); + } + + /* FMPSMBUS Packet Error Check error interrupt occurred ----------------------------------*/ + if (((itflags & FMPSMBUS_FLAG_PECERR) == FMPSMBUS_FLAG_PECERR) && \ + ((itsources & FMPSMBUS_IT_ERRI) == FMPSMBUS_IT_ERRI)) + { + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_PECERR; + + /* Clear PEC error flag */ + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_PECERR); + } + + /* Flush TX register */ + FMPSMBUS_Flush_TXDR(hfmpsmbus); + + /* Store current volatile hfmpsmbus->ErrorCode, misra rule */ + tmperror = hfmpsmbus->ErrorCode; + + /* Call the Error Callback in case of Error detected */ + if ((tmperror != HAL_FMPSMBUS_ERROR_NONE) && (tmperror != HAL_FMPSMBUS_ERROR_ACKF)) + { + /* Do not Reset the HAL state in case of ALERT error */ + if ((tmperror & HAL_FMPSMBUS_ERROR_ALERT) != HAL_FMPSMBUS_ERROR_ALERT) + { + /* Store current volatile hfmpsmbus->State, misra rule */ + tmpstate = hfmpsmbus->State; + + if (((tmpstate & HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_TX) + || ((tmpstate & HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX) == HAL_FMPSMBUS_STATE_SLAVE_BUSY_RX)) + { + /* Reset only HAL_FMPSMBUS_STATE_SLAVE_BUSY_XX */ + /* keep HAL_FMPSMBUS_STATE_LISTEN if set */ + hfmpsmbus->PreviousState = HAL_FMPSMBUS_STATE_READY; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_LISTEN; + } + } + + /* Call the Error callback to inform upper layer */ +#if (USE_HAL_FMPSMBUS_REGISTER_CALLBACKS == 1) + hfmpsmbus->ErrorCallback(hfmpsmbus); +#else + HAL_FMPSMBUS_ErrorCallback(hfmpsmbus); +#endif /* USE_HAL_FMPSMBUS_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Handle FMPSMBUS Communication Timeout. + * @param hfmpsmbus Pointer to a FMPSMBUS_HandleTypeDef structure that contains + * the configuration information for the specified FMPSMBUS. + * @param Flag Specifies the FMPSMBUS flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @retval HAL status + */ +static HAL_StatusTypeDef FMPSMBUS_WaitOnFlagUntilTimeout(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint32_t Flag, + FlagStatus Status, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Wait until flag is set */ + while ((FlagStatus)(__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, Flag)) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0UL)) + { + hfmpsmbus->PreviousState = hfmpsmbus->State; + hfmpsmbus->State = HAL_FMPSMBUS_STATE_READY; + + /* Update FMPSMBUS error code */ + hfmpsmbus->ErrorCode |= HAL_FMPSMBUS_ERROR_HALTIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hfmpsmbus); + + return HAL_ERROR; + } + } + } + + return HAL_OK; +} + +/** + * @brief FMPSMBUS Tx data register flush process. + * @param hfmpsmbus FMPSMBUS handle. + * @retval None + */ +static void FMPSMBUS_Flush_TXDR(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* If a pending TXIS flag is set */ + /* Write a dummy data in TXDR to clear it */ + if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXIS) != RESET) + { + hfmpsmbus->Instance->TXDR = 0x00U; + } + + /* Flush TX register if not empty */ + if (__HAL_FMPSMBUS_GET_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXE) == RESET) + { + __HAL_FMPSMBUS_CLEAR_FLAG(hfmpsmbus, FMPSMBUS_FLAG_TXE); + } +} + +/** + * @brief Handle FMPSMBUSx communication when starting transfer or during transfer (TC or TCR flag are set). + * @param hfmpsmbus FMPSMBUS handle. + * @param DevAddress specifies the slave address to be programmed. + * @param Size specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param Mode New state of the FMPSMBUS START condition generation. + * This parameter can be one or a combination of the following values: + * @arg @ref FMPSMBUS_RELOAD_MODE Enable Reload mode. + * @arg @ref FMPSMBUS_AUTOEND_MODE Enable Automatic end mode. + * @arg @ref FMPSMBUS_SOFTEND_MODE Enable Software end mode and Reload mode. + * @arg @ref FMPSMBUS_SENDPEC_MODE Enable Packet Error Calculation mode. + * @param Request New state of the FMPSMBUS START condition generation. + * This parameter can be one of the following values: + * @arg @ref FMPSMBUS_NO_STARTSTOP Don't Generate stop and start condition. + * @arg @ref FMPSMBUS_GENERATE_STOP Generate stop condition (Size should be set to 0). + * @arg @ref FMPSMBUS_GENERATE_START_READ Generate Restart for read request. + * @arg @ref FMPSMBUS_GENERATE_START_WRITE Generate Restart for write request. + * @retval None + */ +static void FMPSMBUS_TransferConfig(FMPSMBUS_HandleTypeDef *hfmpsmbus, uint16_t DevAddress, uint8_t Size, + uint32_t Mode, uint32_t Request) +{ + /* Check the parameters */ + assert_param(IS_FMPSMBUS_ALL_INSTANCE(hfmpsmbus->Instance)); + assert_param(IS_FMPSMBUS_TRANSFER_MODE(Mode)); + assert_param(IS_FMPSMBUS_TRANSFER_REQUEST(Request)); + + /* update CR2 register */ + MODIFY_REG(hfmpsmbus->Instance->CR2, + ((FMPI2C_CR2_SADD | FMPI2C_CR2_NBYTES | FMPI2C_CR2_RELOAD | FMPI2C_CR2_AUTOEND | \ + (FMPI2C_CR2_RD_WRN & (uint32_t)(Request >> (31UL - FMPI2C_CR2_RD_WRN_Pos))) | \ + FMPI2C_CR2_START | FMPI2C_CR2_STOP | FMPI2C_CR2_PECBYTE)), \ + (uint32_t)(((uint32_t)DevAddress & FMPI2C_CR2_SADD) | \ + (((uint32_t)Size << FMPI2C_CR2_NBYTES_Pos) & FMPI2C_CR2_NBYTES) | \ + (uint32_t)Mode | (uint32_t)Request)); +} + +/** + * @brief Convert FMPSMBUSx OTHER_xxx XferOptions to functional XferOptions. + * @param hfmpsmbus FMPSMBUS handle. + * @retval None + */ +static void FMPSMBUS_ConvertOtherXferOptions(FMPSMBUS_HandleTypeDef *hfmpsmbus) +{ + /* if user set XferOptions to FMPSMBUS_OTHER_FRAME_NO_PEC */ + /* it request implicitly to generate a restart condition */ + /* set XferOptions to FMPSMBUS_FIRST_FRAME */ + if (hfmpsmbus->XferOptions == FMPSMBUS_OTHER_FRAME_NO_PEC) + { + hfmpsmbus->XferOptions = FMPSMBUS_FIRST_FRAME; + } + /* else if user set XferOptions to FMPSMBUS_OTHER_FRAME_WITH_PEC */ + /* it request implicitly to generate a restart condition */ + /* set XferOptions to FMPSMBUS_FIRST_FRAME | FMPSMBUS_SENDPEC_MODE */ + else if (hfmpsmbus->XferOptions == FMPSMBUS_OTHER_FRAME_WITH_PEC) + { + hfmpsmbus->XferOptions = FMPSMBUS_FIRST_FRAME | FMPSMBUS_SENDPEC_MODE; + } + /* else if user set XferOptions to FMPSMBUS_OTHER_AND_LAST_FRAME_NO_PEC */ + /* it request implicitly to generate a restart condition */ + /* then generate a stop condition at the end of transfer */ + /* set XferOptions to FMPSMBUS_FIRST_AND_LAST_FRAME_NO_PEC */ + else if (hfmpsmbus->XferOptions == FMPSMBUS_OTHER_AND_LAST_FRAME_NO_PEC) + { + hfmpsmbus->XferOptions = FMPSMBUS_FIRST_AND_LAST_FRAME_NO_PEC; + } + /* else if user set XferOptions to FMPSMBUS_OTHER_AND_LAST_FRAME_WITH_PEC */ + /* it request implicitly to generate a restart condition */ + /* then generate a stop condition at the end of transfer */ + /* set XferOptions to FMPSMBUS_FIRST_AND_LAST_FRAME_WITH_PEC */ + else if (hfmpsmbus->XferOptions == FMPSMBUS_OTHER_AND_LAST_FRAME_WITH_PEC) + { + hfmpsmbus->XferOptions = FMPSMBUS_FIRST_AND_LAST_FRAME_WITH_PEC; + } + else + { + /* Nothing to do */ + } +} +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#endif /* HAL_FMPSMBUS_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus_ex.c new file mode 100644 index 0000000..14ca0b4 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_fmpsmbus_ex.c @@ -0,0 +1,145 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_fmpsmbus_ex.c + * @author MCD Application Team + * @brief FMPSMBUS Extended HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of FMPSMBUS Extended peripheral: + * + Extended features 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 + ============================================================================== + ##### FMPSMBUS peripheral Extended features ##### + ============================================================================== + + [..] Comparing to other previous devices, the FMPSMBUS interface for STM32F4xx + devices contains the following additional features + + (+) Disable or enable Fast Mode Plus + + ##### How to use this driver ##### + ============================================================================== + (#) Configure the enable or disable of fast mode plus driving capability using the functions : + (++) HAL_FMPSMBUSEx_EnableFastModePlus() + (++) HAL_FMPSMBUSEx_DisableFastModePlus() + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup FMPSMBUSEx FMPSMBUSEx + * @brief FMPSMBUS Extended HAL module driver + * @{ + */ + +#ifdef HAL_FMPSMBUS_MODULE_ENABLED +#if defined(FMPI2C_CR1_PE) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup FMPSMBUSEx_Exported_Functions FMPSMBUS Extended Exported Functions + * @{ + */ + +/** @defgroup FMPSMBUSEx_Exported_Functions_Group3 Fast Mode Plus Functions + * @brief Fast Mode Plus Functions + * +@verbatim + =============================================================================== + ##### Fast Mode Plus Functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Fast Mode Plus + +@endverbatim + * @{ + */ + +/** + * @brief Enable the FMPSMBUS fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref FMPSMBUSEx_FastModePlus values + * @note For FMPI2C1, fast mode plus driving capability can be enabled on all selected + * FMPI2C1 pins using FMPSMBUS_FASTMODEPLUS_FMPI2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining FMPI2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be enabled only by using FMPSMBUS_FASTMODEPLUS_FMPI2C1 parameter. + * @retval None + */ +void HAL_FMPSMBUSEx_EnableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_FMPSMBUS_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Enable fast mode plus driving capability for selected pin */ + SET_BIT(SYSCFG->CFGR, (uint32_t)ConfigFastModePlus); +} + +/** + * @brief Disable the FMPSMBUS fast mode plus driving capability. + * @param ConfigFastModePlus Selects the pin. + * This parameter can be one of the @ref FMPSMBUSEx_FastModePlus values + * @note For FMPI2C1, fast mode plus driving capability can be disabled on all selected + * FMPI2C1 pins using FMPSMBUS_FASTMODEPLUS_FMPI2C1 parameter or independently + * on each one of the following pins PB6, PB7, PB8 and PB9. + * @note For remaining FMPI2C1 pins (PA14, PA15...) fast mode plus driving capability + * can be disabled only by using FMPSMBUS_FASTMODEPLUS_FMPI2C1 parameter. + * @retval None + */ +void HAL_FMPSMBUSEx_DisableFastModePlus(uint32_t ConfigFastModePlus) +{ + /* Check the parameter */ + assert_param(IS_FMPSMBUS_FASTMODEPLUS(ConfigFastModePlus)); + + /* Enable SYSCFG clock */ + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Disable fast mode plus driving capability for selected pin */ + CLEAR_BIT(SYSCFG->CFGR, (uint32_t)ConfigFastModePlus); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#endif /* HAL_FMPSMBUS_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/hal/stm32f4xx_hal_gpio.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c similarity index 100% rename from libs/hal/stm32f4xx_hal_gpio.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_gpio.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c new file mode 100644 index 0000000..f3aafe0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash.c @@ -0,0 +1,3514 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hash.c + * @author MCD Application Team + * @brief HASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the HASH peripheral: + * + Initialization and de-initialization methods + * + HASH or HMAC processing in polling mode + * + HASH or HMAC processing in interrupt mode + * + HASH or HMAC processing in DMA mode + * + Peripheral State methods + * + HASH or HMAC processing suspension/resumption + * + ****************************************************************************** + * @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 HASH HAL driver can be used as follows: + + (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit(): + (##) Enable the HASH interface clock using __HASH_CLK_ENABLE() + (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT()) + (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority() + (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ() + (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API + (##) When resorting to DMA-based APIs (e.g. HAL_HASH_xxx_Start_DMA()) + (+++) Enable the DMAx interface clock using + __DMAx_CLK_ENABLE() + (+++) Configure and enable one DMA stream to manage data transfer from + memory to peripheral (input stream). Managing data transfer from + peripheral to memory can be performed only using CPU. + (+++) Associate the initialized DMA handle to the HASH DMA handle + using __HAL_LINKDMA() + (+++) Configure the priority and enable the NVIC for the transfer complete + interrupt on the DMA stream: use + HAL_NVIC_SetPriority() and + HAL_NVIC_EnableIRQ() + + (#)Initialize the HASH HAL using HAL_HASH_Init(). This function: + (##) resorts to HAL_HASH_MspInit() for low-level initialization, + (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit. + + (#)Three processing schemes are available: + (##) Polling mode: processing APIs are blocking functions + i.e. they process the data and wait till the digest computation is finished, + e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC + (##) Interrupt mode: processing APIs are not blocking functions + i.e. they process the data under interrupt, + e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC + (##) DMA mode: processing APIs are not blocking functions and the CPU is + not used for data transfer i.e. the data transfer is ensured by DMA, + e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA() + for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish() + is then required to retrieve the digest. + + (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is + initialized and processes the buffer fed in input. When the input data have all been + fed to the Peripheral, the digest computation can start. + + (#)Multi-buffer processing is possible in polling, interrupt and DMA modes. + (##) In polling mode, only multi-buffer HASH processing is possible. + API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one. + User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as + well the computed digest. + + (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer, + except for the last one. + User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as + well the computed digest. + + (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. + (+++) HASH processing: once initialization is done, MDMAT bit must be set + through __HAL_HASH_SET_MDMAT() macro. + From that point, each buffer can be fed to the Peripheral through HAL_HASH_xxx_Start_DMA() API. + Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() + macro then wrap-up the HASH processing in feeding the last input buffer through the + same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to + API HAL_HASH_xxx_Finish(). + (+++) HMAC processing (requires to resort to extended functions): + after initialization, the key and the first input buffer are entered + in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and + starts step 2. + The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this + point, the HMAC processing is still carrying out step 2. + Then, step 2 for the last input buffer and step 3 are carried out by a single call + to HAL_HMACEx_xxx_Step2_3_DMA(). + + The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish(). + + + (#)Context swapping. + (##) Two APIs are available to suspend HASH or HMAC processing: + (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode), + (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA. + + (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows + to save in memory the Peripheral context. This context can be restored afterwards + to resume the HASH processing thanks to HAL_HASH_ContextRestoring(). + + (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension + time, processing can be restarted with the same API call (same API, same handle, + same parameters) as done before the suspension. Relevant parameters to restart at + the proper location are internally saved in the HASH handle. + + (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral. + + *** Remarks on message length *** + =================================== + [..] + (#) HAL in interruption mode (interruptions driven) + + (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes. + This is why, for driver implementation simplicity’s sake, user is requested to enter a message the + length of which is a multiple of 4 bytes. + + (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR + to specify which bits to discard at the end of the complete message to process only the message bits + and not extra bits. + + (##) If user needs to perform a hash computation of a large input buffer that is spread around various places + in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes + necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral. + It is advised to the user to + (+++) achieve the first formatting operation by software then enter the data + (+++) while the Peripheral is processing the first input set, carry out the second formatting + operation by software, to be ready when DINIS occurs. + (+++) repeat step 2 until the whole message is processed. + + [..] + (#) HAL in DMA mode + + (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis. + The same field described above in HASH_STR is used to specify which bits to discard at the end of the + DMA transfer to process only the message bits and not extra bits. Due to hardware implementation, + this is possible only at the end of the complete message. When several DMA transfers are needed to + enter the message, this is not applicable at the end of the intermediary transfers. + + (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive + chunks of data by software while the DMA transfer and processing is on-going for the first parts of + the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the + software formatting operation is more complex than in the IT mode. + + *** Callback registration *** + =================================== + [..] + (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use function HAL_HASH_RegisterCallback() to register a user callback. + + (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks: + (+) InCpltCallback : callback for input completion. + (+) DgstCpltCallback : callback for digest computation completion. + (+) ErrorCallback : callback for error. + (+) MspInitCallback : HASH MspInit. + (+) MspDeInitCallback : HASH MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) InCpltCallback : callback for input completion. + (+) DgstCpltCallback : callback for digest computation completion. + (+) ErrorCallback : callback for error. + (+) MspInitCallback : HASH MspInit. + (+) MspDeInitCallback : HASH MspDeInit. + + (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions: + examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback() + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_HASH_Init + and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand) + If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_HASH_RegisterCallback before calling HAL_HASH_DeInit + or HAL_HASH_Init function. + + When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (HASH) + +/** @defgroup HASH HASH + * @brief HASH HAL module driver. + * @{ + */ + +#ifdef HAL_HASH_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup HASH_Private_Constants HASH Private Constants + * @{ + */ + +/** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status + * @{ + */ +#define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */ +#define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */ +/** + * @} + */ + +/** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers + * @{ + */ +#define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */ +/** + * @} + */ + +/** @defgroup HASH_TimeOut_Value HASH TimeOut Value + * @{ + */ +#define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */ +/** + * @} + */ + +/** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit + * @{ + */ +#define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */ +/** + * @} + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup HASH_Private_Functions HASH Private Functions + * @{ + */ +static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma); +static void HASH_DMAError(DMA_HandleTypeDef *hdma); +static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size); +static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, + uint32_t Timeout); +static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size); +static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash); +static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash); +static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout); +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions HASH Exported Functions + * @{ + */ + +/** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization, configuration and call-back functions. + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the HASH according to the specified parameters + in the HASH_InitTypeDef and create the associated handle + (+) DeInitialize the HASH peripheral + (+) Initialize the HASH MCU Specific Package (MSP) + (+) DeInitialize the HASH MSP + + [..] This section provides as well call back functions definitions for user + code to manage: + (+) Input data transfer to Peripheral completion + (+) Calculated digest retrieval completion + (+) Error management + + + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the HASH according to the specified parameters in the + HASH_HandleTypeDef and create the associated handle. + * @note Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(), + * other configuration bits are set by HASH or HMAC processing APIs. + * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for + * multi-buffer HASH processing, user needs to resort to + * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the + * relevant APIs manage themselves the MDMAT bit. + * @param hhash HASH handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash) +{ + /* Check the hash handle allocation */ + if (hhash == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_HASH_DATATYPE(hhash->Init.DataType)); + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + if (hhash->State == HAL_HASH_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hhash->Lock = HAL_UNLOCKED; + + /* Reset Callback pointers in HAL_HASH_STATE_RESET only */ + hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ + hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation + completion callback */ + hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ + if (hhash->MspInitCallback == NULL) + { + hhash->MspInitCallback = HAL_HASH_MspInit; + } + + /* Init the low level hardware */ + hhash->MspInitCallback(hhash); + } +#else + if (hhash->State == HAL_HASH_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hhash->Lock = HAL_UNLOCKED; + + /* Init the low level hardware */ + HAL_HASH_MspInit(hhash); + } +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */ + hhash->HashInCount = 0; + hhash->HashBuffSize = 0; + hhash->HashITCounter = 0; + hhash->NbWordsAlreadyPushed = 0; + /* Reset digest calculation bridle (MDMAT bit control) */ + hhash->DigestCalculationDisable = RESET; + /* Set phase to READY */ + hhash->Phase = HAL_HASH_PHASE_READY; + /* Reset suspension request flag */ + hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; + + /* Set the data type bit */ + MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType); +#if defined(HASH_CR_MDMAT) + /* Reset MDMAT bit */ + __HAL_HASH_RESET_MDMAT(); +#endif /* HASH_CR_MDMAT */ + /* Reset HASH handle status */ + hhash->Status = HAL_OK; + + /* Set the HASH state to Ready */ + hhash->State = HAL_HASH_STATE_READY; + + /* Initialise the error code */ + hhash->ErrorCode = HAL_HASH_ERROR_NONE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief DeInitialize the HASH peripheral. + * @param hhash HASH handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash) +{ + /* Check the HASH handle allocation */ + if (hhash == NULL) + { + return HAL_ERROR; + } + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Set the default HASH phase */ + hhash->Phase = HAL_HASH_PHASE_READY; + + /* Reset HashInCount, HashITCounter and HashBuffSize */ + hhash->HashInCount = 0; + hhash->HashBuffSize = 0; + hhash->HashITCounter = 0; + /* Reset digest calculation bridle (MDMAT bit control) */ + hhash->DigestCalculationDisable = RESET; + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + if (hhash->MspDeInitCallback == NULL) + { + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; + } + + /* DeInit the low level hardware */ + hhash->MspDeInitCallback(hhash); +#else + /* DeInit the low level hardware: CLOCK, NVIC */ + HAL_HASH_MspDeInit(hhash); +#endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */ + + + /* Reset HASH handle status */ + hhash->Status = HAL_OK; + + /* Set the HASH state to Ready */ + hhash->State = HAL_HASH_STATE_RESET; + + /* Initialise the error code */ + hhash->ErrorCode = HAL_HASH_ERROR_NONE; + + /* Reset multi buffers accumulation flag */ + hhash->Accumulation = 0U; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initialize the HASH MSP. + * @param hhash HASH handle. + * @retval None + */ +__weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* NOTE : This function should not be modified; when the callback is needed, + HAL_HASH_MspInit() can be implemented in the user file. + */ +} + +/** + * @brief DeInitialize the HASH MSP. + * @param hhash HASH handle. + * @retval None + */ +__weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* NOTE : This function should not be modified; when the callback is needed, + HAL_HASH_MspDeInit() can be implemented in the user file. + */ +} + +/** + * @brief Input data transfer complete call back. + * @note HAL_HASH_InCpltCallback() is called when the complete input message + * has been fed to the Peripheral. This API is invoked only when input data are + * entered under interruption or through DMA. + * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set), + * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding + * to the Peripheral. + * @param hhash HASH handle. + * @retval None + */ +__weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* NOTE : This function should not be modified; when the callback is needed, + HAL_HASH_InCpltCallback() can be implemented in the user file. + */ +} + +/** + * @brief Digest computation complete call back. + * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not + * relevant with DMA. + * @param hhash HASH handle. + * @retval None + */ +__weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* NOTE : This function should not be modified; when the callback is needed, + HAL_HASH_DgstCpltCallback() can be implemented in the user file. + */ +} + +/** + * @brief Error callback. + * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...) + * to retrieve the error type. + * @param hhash HASH handle. + * @retval None + */ +__weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* NOTE : This function should not be modified; when the callback is needed, + HAL_HASH_ErrorCallback() can be implemented in the user file. + */ +} + +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User HASH Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hhash HASH handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID + * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID + * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID + * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID + * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, + pHASH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hhash); + + if (HAL_HASH_STATE_READY == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_INPUTCPLT_CB_ID : + hhash->InCpltCallback = pCallback; + break; + + case HAL_HASH_DGSTCPLT_CB_ID : + hhash->DgstCpltCallback = pCallback; + break; + + case HAL_HASH_ERROR_CB_ID : + hhash->ErrorCallback = pCallback; + break; + + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = pCallback; + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_HASH_STATE_RESET == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = pCallback; + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhash); + return status; +} + +/** + * @brief Unregister a HASH Callback + * HASH Callback is redirected to the weak (surcharged) predefined callback + * @param hhash HASH handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID + * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID + * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID + * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID + * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hhash); + + if (HAL_HASH_STATE_READY == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_INPUTCPLT_CB_ID : + hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */ + break; + + case HAL_HASH_DGSTCPLT_CB_ID : + hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation + completion callback */ + break; + + case HAL_HASH_ERROR_CB_ID : + hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */ + break; + + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_HASH_STATE_RESET == hhash->State) + { + switch (CallbackID) + { + case HAL_HASH_MSPINIT_CB_ID : + hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */ + break; + + case HAL_HASH_MSPDEINIT_CB_ID : + hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */ + break; + + default : + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhash); + return status; +} +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode + * @brief HASH processing functions using polling mode. + * +@verbatim + =============================================================================== + ##### Polling mode HASH processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in polling mode + the hash value using one of the following algorithms: + (+) MD5 + (++) HAL_HASH_MD5_Start() + (++) HAL_HASH_MD5_Accmlt() + (++) HAL_HASH_MD5_Accmlt_End() + (+) SHA1 + (++) HAL_HASH_SHA1_Start() + (++) HAL_HASH_SHA1_Accmlt() + (++) HAL_HASH_SHA1_Accmlt_End() + + [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). + + [..] In case of multi-buffer HASH processing (a single digest is computed while + several buffers are fed to the Peripheral), the user can resort to successive calls + to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call + to HAL_HASH_xxx_Accumulate_End(). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief If not already done, initialize the HASH peripheral in MD5 mode then + * processes pInBuffer. + * @note Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_MD5_Accmlt_End(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief If not already done, initialize the HASH peripheral in SHA1 mode then + * processes pInBuffer. + * @note Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_SHA1_Accmlt_End(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); +} + +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode + * @brief HASH processing functions using interrupt mode. + * +@verbatim + =============================================================================== + ##### Interruption mode HASH processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in interrupt mode + the hash value using one of the following algorithms: + (+) MD5 + (++) HAL_HASH_MD5_Start_IT() + (++) HAL_HASH_MD5_Accmlt_IT() + (++) HAL_HASH_MD5_Accmlt_End_IT() + (+) SHA1 + (++) HAL_HASH_SHA1_Start_IT() + (++) HAL_HASH_SHA1_Accmlt_IT() + (++) HAL_HASH_SHA1_Accmlt_End_IT() + + [..] API HAL_HASH_IRQHandler() manages each HASH interruption. + + [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in + HMAC processing mode. + + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief If not already done, initialize the HASH peripheral in MD5 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_MD5_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); +} + + +/** + * @brief If not already done, initialize the HASH peripheral in SHA1 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASH_SHA1_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief Handle HASH interrupt request. + * @param hhash HASH handle. + * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well. + * @note In case of error reported during the HASH interruption processing, + * HAL_HASH_ErrorCallback() API is called so that user code can + * manage the error. The error type is available in hhash->Status field. + * @retval None + */ +void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash) +{ + hhash->Status = HASH_IT(hhash); + if (hhash->Status != HAL_OK) + { + hhash->ErrorCode |= HAL_HASH_ERROR_IT; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->ErrorCallback(hhash); +#else + HAL_HASH_ErrorCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + /* After error handling by code user, reset HASH handle HAL status */ + hhash->Status = HAL_OK; + } +} + +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode + * @brief HASH processing functions using DMA mode. + * +@verbatim + =============================================================================== + ##### DMA mode HASH processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in DMA mode + the hash value using one of the following algorithms: + (+) MD5 + (++) HAL_HASH_MD5_Start_DMA() + (++) HAL_HASH_MD5_Finish() + (+) SHA1 + (++) HAL_HASH_SHA1_Start_DMA() + (++) HAL_HASH_SHA1_Finish() + + [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort + to HAL_HASH_xxx_Start_DMA() then read the resulting digest with + HAL_HASH_xxx_Finish(). + [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before + the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be + reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally + retrieved thanks to HAL_HASH_xxx_Finish(). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer + * to feed the input buffer to the Peripheral. + * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must + * be called to retrieve the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief Return the computed digest in MD5 mode. + * @note The API waits for DCIS to be set then reads the computed digest. + * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in + * HMAC MD5 mode. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Finish(hhash, pOutBuffer, Timeout); +} + +/** + * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer + * to feed the input buffer to the Peripheral. + * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must + * be called to retrieve the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + + +/** + * @brief Return the computed digest in SHA1 mode. + * @note The API waits for DCIS to be set then reads the computed digest. + * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in + * HMAC SHA1 mode. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Finish(hhash, pOutBuffer, Timeout); +} + +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode + * @brief HMAC processing functions using polling mode. + * +@verbatim + =============================================================================== + ##### Polling mode HMAC processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in polling mode + the HMAC value using one of the following algorithms: + (+) MD5 + (++) HAL_HMAC_MD5_Start() + (+) SHA1 + (++) HAL_HMAC_SHA1_Start() + + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout) +{ + return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout) +{ + return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1); +} + +/** + * @} + */ + + +/** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode + * @brief HMAC processing functions using interrupt mode. + * +@verbatim + =============================================================================== + ##### Interrupt mode HMAC processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in interrupt mode + the HMAC value using one of the following algorithms: + (+) MD5 + (++) HAL_HMAC_MD5_Start_IT() + (+) SHA1 + (++) HAL_HMAC_SHA1_Start_IT() + +@endverbatim + * @{ + */ + + +/** + * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then + * read the computed digest in interrupt mode. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 16 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then + * read the computed digest in interrupt mode. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 20 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1); +} + +/** + * @} + */ + + + +/** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode + * @brief HMAC processing functions using DMA modes. + * +@verbatim + =============================================================================== + ##### DMA mode HMAC processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in DMA mode + the HMAC value using one of the following algorithms: + (+) MD5 + (++) HAL_HMAC_MD5_Start_DMA() + (+) SHA1 + (++) HAL_HMAC_SHA1_Start_DMA() + + [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing, + user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest + with HAL_HASH_xxx_Finish(). + +@endverbatim + * @{ + */ + + +/** + * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required + * DMA transfers to feed the key and the input buffer to the Peripheral. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve + * the computed digest. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note If MDMAT bit is set before calling this function (multi-buffer + * HASH processing case), the input buffer size (in bytes) must be + * a multiple of 4 otherwise, the HASH digest computation is corrupted. + * For the processing of the last buffer of the thread, MDMAT bit must + * be reset and the buffer length (in bytes) doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + + +/** + * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required + * DMA transfers to feed the key and the input buffer to the Peripheral. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve + * the computed digest. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note If MDMAT bit is set before calling this function (multi-buffer + * HASH processing case), the input buffer size (in bytes) must be + * a multiple of 4 otherwise, the HASH digest computation is corrupted. + * For the processing of the last buffer of the thread, MDMAT bit must + * be reset and the buffer length (in bytes) doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @} + */ + +/** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions + * @brief Peripheral State functions. + * +@verbatim + =============================================================================== + ##### Peripheral State methods ##### + =============================================================================== + [..] + This section permits to get in run-time the state and the peripheral handle + status of the peripheral: + (+) HAL_HASH_GetState() + (+) HAL_HASH_GetStatus() + + [..] + Additionally, this subsection provides functions allowing to save and restore + the HASH or HMAC processing context in case of calculation suspension: + (+) HAL_HASH_ContextSaving() + (+) HAL_HASH_ContextRestoring() + + [..] + This subsection provides functions allowing to suspend the HASH processing + (+) when input are fed to the Peripheral by software + (++) HAL_HASH_SwFeed_ProcessSuspend() + (+) when input are fed to the Peripheral by DMA + (++) HAL_HASH_DMAFeed_ProcessSuspend() + + + +@endverbatim + * @{ + */ + +/** + * @brief Return the HASH handle state. + * @note The API yields the current state of the handle (BUSY, READY,...). + * @param hhash HASH handle. + * @retval HAL HASH state + */ +HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash) +{ + return hhash->State; +} + + +/** + * @brief Return the HASH HAL status. + * @note The API yields the HAL status of the handle: it is the result of the + * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT). + * @param hhash HASH handle. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash) +{ + return hhash->Status; +} + +/** + * @brief Save the HASH context in case of processing suspension. + * @param hhash HASH handle. + * @param pMemBuffer pointer to the memory buffer where the HASH context + * is saved. + * @note The IMR, STR, CR then all the CSR registers are saved + * in that order. Only the r/w bits are read to be restored later on. + * @note By default, all the context swap registers (there are + * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved. + * @note pMemBuffer points to a buffer allocated by the user. The buffer size + * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long. + * @retval None + */ +void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) +{ + uint32_t mem_ptr = (uint32_t)pMemBuffer; + uint32_t csr_ptr = (uint32_t)HASH->CSR; + uint32_t i; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* Save IMR register content */ + *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI); + mem_ptr += 4U; + /* Save STR register content */ + *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW); + mem_ptr += 4U; + /* Save CR register content */ +#if defined(HASH_CR_MDMAT) + *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO | + HASH_CR_LKEY | HASH_CR_MDMAT); +#else + *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO | + HASH_CR_LKEY); +#endif /* HASH_CR_MDMAT*/ + mem_ptr += 4U; + /* By default, save all CSRs registers */ + for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) + { + *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr); + mem_ptr += 4U; + csr_ptr += 4U; + } +} + + +/** + * @brief Restore the HASH context in case of processing resumption. + * @param hhash HASH handle. + * @param pMemBuffer pointer to the memory buffer where the HASH context + * is stored. + * @note The IMR, STR, CR then all the CSR registers are restored + * in that order. Only the r/w bits are restored. + * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS + * of those) are restored (all of them have been saved by default + * beforehand). + * @retval None + */ +void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer) +{ + uint32_t mem_ptr = (uint32_t)pMemBuffer; + uint32_t csr_ptr = (uint32_t)HASH->CSR; + uint32_t i; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhash); + + /* Restore IMR register content */ + WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr))); + mem_ptr += 4U; + /* Restore STR register content */ + WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr))); + mem_ptr += 4U; + /* Restore CR register content */ + WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr))); + mem_ptr += 4U; + + /* Reset the HASH processor before restoring the Context + Swap Registers (CSR) */ + __HAL_HASH_INIT(); + + /* By default, restore all CSR registers */ + for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--) + { + WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr))); + mem_ptr += 4U; + csr_ptr += 4U; + } +} + + +/** + * @brief Initiate HASH processing suspension when in polling or interruption mode. + * @param hhash HASH handle. + * @note Set the handle field SuspendRequest to the appropriate value so that + * the on-going HASH processing is suspended as soon as the required + * conditions are met. Note that the actual suspension is carried out + * by the functions HASH_WriteData() in polling mode and HASH_IT() in + * interruption mode. + * @retval None + */ +void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) +{ + /* Set Handle Suspend Request field */ + hhash->SuspendRequest = HAL_HASH_SUSPEND; +} + +/** + * @brief Suspend the HASH processing when in DMA mode. + * @param hhash HASH handle. + * @note When suspension attempt occurs at the very end of a DMA transfer and + * all the data have already been entered in the Peripheral, hhash->State is + * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is + * recommended to wrap-up the processing in reading the digest as usual. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash) +{ + uint32_t tmp_remaining_DMATransferSize_inWords; + uint32_t tmp_initial_DMATransferSize_inWords; + uint32_t tmp_words_already_pushed; + + if (hhash->State == HAL_HASH_STATE_READY) + { + return HAL_ERROR; + } + else + { + + /* Make sure there is enough time to suspend the processing */ + tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; + + if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT) + { + /* No suspension attempted since almost to the end of the transferred data. */ + /* Best option for user code is to wrap up low priority message hashing */ + return HAL_ERROR; + } + + /* Wait for BUSY flag to be reset */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) + { + return HAL_ERROR; + } + + /* Wait for BUSY flag to be set */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK) + { + return HAL_TIMEOUT; + } + /* Disable DMA channel */ + /* Note that the Abort function will + - Clear the transfer error flags + - Unlock + - Set the State + */ + if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear DMAE bit */ + CLEAR_BIT(HASH->CR, HASH_CR_DMAE); + + /* Wait for BUSY flag to be reset */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET) + { + return HAL_ERROR; + } + + /* At this point, DMA interface is disabled and no transfer is on-going */ + /* Retrieve from the DMA handle how many words remain to be written */ + tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR; + + if (tmp_remaining_DMATransferSize_inWords == 0U) + { + /* All the DMA transfer is actually done. Suspension occurred at the very end + of the transfer. Either the digest computation is about to start (HASH case) + or processing is about to move from one step to another (HMAC case). + In both cases, the processing can't be suspended at this point. It is + safer to + - retrieve the low priority block digest before starting the high + priority block processing (HASH case) + - re-attempt a new suspension (HMAC case) + */ + return HAL_ERROR; + } + else + { + + /* Compute how many words were supposed to be transferred by DMA */ + tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \ + ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U)); + + /* If discrepancy between the number of words reported by DMA Peripheral and + the numbers of words entered as reported by HASH Peripheral, correct it */ + /* tmp_words_already_pushed reflects the number of words that were already pushed before + the start of DMA transfer (multi-buffer processing case) */ + tmp_words_already_pushed = hhash->NbWordsAlreadyPushed; + if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \ + tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED()) + { + tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */ + } + + /* Accordingly, update the input pointer that points at the next word to be + transferred to the Peripheral by DMA */ + hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ; + + /* And store in HashInCount the remaining size to transfer (in bytes) */ + hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords; + + } + + /* Set State as suspended */ + hhash->State = HAL_HASH_STATE_SUSPENDED; + + return HAL_OK; + + } +} + +/** + * @brief Return the HASH handle error code. + * @param hhash pointer to a HASH_HandleTypeDef structure. + * @retval HASH Error Code + */ +uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash) +{ + /* Return HASH Error Code */ + return hhash->ErrorCode; +} +/** + * @} + */ + + +/** + * @} + */ + +/** @defgroup HASH_Private_Functions HASH Private Functions + * @{ + */ + +/** + * @brief DMA HASH Input Data transfer completion callback. + * @param hdma DMA handle. + * @note In case of HMAC processing, HASH_DMAXferCplt() initiates + * the next DMA transfer for the following HMAC step. + * @retval None + */ +static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma) +{ + HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + uint32_t inputaddr; + uint32_t buffersize; + HAL_StatusTypeDef status = HAL_OK; + + if (hhash->State != HAL_HASH_STATE_SUSPENDED) + { + + /* Disable the DMA transfer */ + CLEAR_BIT(HASH->CR, HASH_CR_DMAE); + + if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U) + { + /* If no HMAC processing, input data transfer is now over */ + + /* Change the HASH state to ready */ + hhash->State = HAL_HASH_STATE_READY; + + /* Call Input data transfer complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + } + else + { + /* HMAC processing: depending on the current HMAC step and whether or + not multi-buffer processing is on-going, the next step is initiated + and MDMAT bit is set. */ + + + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) + { + /* This is the end of HMAC processing */ + + /* Change the HASH state to ready */ + hhash->State = HAL_HASH_STATE_READY; + + /* Call Input data transfer complete call back + (note that the last DMA transfer was that of the key + for the outer HASH operation). */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + return; + } + else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) + { + inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */ + buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ + + /* In case of suspension request, save the new starting parameters */ + hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */ + hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */ + + hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ +#if defined(HASH_CR_MDMAT) + /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */ + if (hhash->DigestCalculationDisable != RESET) + { + /* Digest calculation is disabled: Step 2 must start with MDMAT bit set, + no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */ + __HAL_HASH_SET_MDMAT(); + } +#endif /* HASH_CR_MDMAT*/ + } + else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/ + { + if (hhash->DigestCalculationDisable != RESET) + { + /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral + (case of multi-buffer HMAC processing): + DCAL must not be set. + Phase remains in Step 2, MDMAT remains set at this point. + Change the HASH state to ready and call Input data transfer complete call back. */ + hhash->State = HAL_HASH_STATE_READY; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + return ; + } + else + { + /* Digest calculation is not disabled (case of single buffer input or last buffer + of multi-buffer HMAC processing) */ + inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */ + buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ + /* In case of suspension request, save the new starting parameters */ + hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */ + hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */ + + hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */ + } + } + + /* Configure the Number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(buffersize); + + /* Set the HASH DMA transfer completion call back */ + hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; + + /* Enable the DMA In DMA stream */ + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ + (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \ + (buffersize / 4U))); + + /* Enable DMA requests */ + SET_BIT(HASH->CR, HASH_CR_DMAE); + + /* Return function status */ + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + else + { + /* Change HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + } + } + } + + return; +} + +/** + * @brief DMA HASH communication error callback. + * @param hdma DMA handle. + * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that + * can contain user code to manage the error. + * @retval None + */ +static void HASH_DMAError(DMA_HandleTypeDef *hdma) +{ + HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + if (hhash->State != HAL_HASH_STATE_SUSPENDED) + { + hhash->ErrorCode |= HAL_HASH_ERROR_DMA; + /* Set HASH state to ready to prevent any blocking issue in user code + present in HAL_HASH_ErrorCallback() */ + hhash->State = HAL_HASH_STATE_READY; + /* Set HASH handle status to error */ + hhash->Status = HAL_ERROR; +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->ErrorCallback(hhash); +#else + HAL_HASH_ErrorCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + /* After error handling by code user, reset HASH handle HAL status */ + hhash->Status = HAL_OK; + + } +} + +/** + * @brief Feed the input buffer to the HASH Peripheral. + * @param hhash HASH handle. + * @param pInBuffer pointer to input buffer. + * @param Size the size of input buffer in bytes. + * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether + * or not the HASH processing must be suspended. If this is the case, the + * processing is suspended when possible and the Peripheral feeding point reached at + * suspension time is stored in the handle for resumption later on. + * @retval HAL status + */ +static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + uint32_t buffercounter; + __IO uint32_t inputaddr = (uint32_t) pInBuffer; + + for (buffercounter = 0U; buffercounter < Size; buffercounter += 4U) + { + /* Write input data 4 bytes at a time */ + HASH->DIN = *(uint32_t *)inputaddr; + inputaddr += 4U; + + /* If the suspension flag has been raised and if the processing is not about + to end, suspend processing */ + if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter + 4U) < Size)) + { + /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free + in the input buffer */ + if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) + { + /* Reset SuspendRequest */ + hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; + + /* Depending whether the key or the input data were fed to the Peripheral, the feeding point + reached at suspension time is not saved in the same handle fields */ + if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)) + { + /* Save current reading and writing locations of Input and Output buffers */ + hhash->pHashInBuffPtr = (uint8_t *)inputaddr; + /* Save the number of bytes that remain to be processed at this point */ + hhash->HashInCount = Size - (buffercounter + 4U); + } + else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) + { + /* Save current reading and writing locations of Input and Output buffers */ + hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr; + /* Save the number of bytes that remain to be processed at this point */ + hhash->HashKeyCount = Size - (buffercounter + 4U); + } + else + { + /* Unexpected phase: unlock process and report error */ + hhash->State = HAL_HASH_STATE_READY; + __HAL_UNLOCK(hhash); + return HAL_ERROR; + } + + /* Set the HASH state to Suspended and exit to stop entering data */ + hhash->State = HAL_HASH_STATE_SUSPENDED; + + return HAL_OK; + } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */ + } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */ + } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */ + + /* At this point, all the data have been entered to the Peripheral: exit */ + return HAL_OK; +} + +/** + * @brief Retrieve the message digest. + * @param pMsgDigest pointer to the computed digest. + * @param Size message digest size in bytes. + * @retval None + */ +static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size) +{ + uint32_t msgdigest = (uint32_t)pMsgDigest; + + switch (Size) + { + /* Read the message digest */ + case 16: /* MD5 */ + *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); + break; + case 20: /* SHA1 */ + *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); + break; + case 28: /* SHA224 */ + *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); +#if defined(HASH_CR_MDMAT) + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); +#endif /* HASH_CR_MDMAT*/ + break; + case 32: /* SHA256 */ + *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]); +#if defined(HASH_CR_MDMAT) + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]); + msgdigest += 4U; + *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]); +#endif /* HASH_CR_MDMAT*/ + break; + default: + break; + } +} + + + +/** + * @brief Handle HASH processing Timeout. + * @param hhash HASH handle. + * @param Flag specifies the HASH flag to check. + * @param Status the Flag status (SET or RESET). + * @param Timeout Timeout duration. + * @retval HAL status + */ +static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, + uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + /* Wait until flag is set */ + if (Status == RESET) + { + while (__HAL_HASH_GET_FLAG(Flag) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Set State to Ready to be able to restart later on */ + hhash->State = HAL_HASH_STATE_READY; + /* Store time out issue in handle status */ + hhash->Status = HAL_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + return HAL_TIMEOUT; + } + } + } + } + else + { + while (__HAL_HASH_GET_FLAG(Flag) != RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Set State to Ready to be able to restart later on */ + hhash->State = HAL_HASH_STATE_READY; + /* Store time out issue in handle status */ + hhash->Status = HAL_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + return HAL_TIMEOUT; + } + } + } + } + return HAL_OK; +} + + +/** + * @brief HASH processing in interruption mode. + * @param hhash HASH handle. + * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether + * or not the HASH processing must be suspended. If this is the case, the + * processing is suspended when possible and the Peripheral feeding point reached at + * suspension time is stored in the handle for resumption later on. + * @retval HAL status + */ +static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash) +{ + if (hhash->State == HAL_HASH_STATE_BUSY) + { + /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */ + if (hhash->HashITCounter == 0U) + { + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + /* HASH state set back to Ready to prevent any issue in user code + present in HAL_HASH_ErrorCallback() */ + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + else if (hhash->HashITCounter == 1U) + { + /* This is the first call to HASH_IT, the first input data are about to be + entered in the Peripheral. A specific processing is carried out at this point to + start-up the processing. */ + hhash->HashITCounter = 2U; + } + else + { + /* Cruise speed reached, HashITCounter remains equal to 3 until the end of + the HASH processing or the end of the current step for HMAC processing. */ + hhash->HashITCounter = 3U; + } + + /* If digest is ready */ + if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS)) + { + /* Read the digest */ + HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); + + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + /* Call digest computation complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->DgstCpltCallback(hhash); +#else + HAL_HASH_DgstCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + return HAL_OK; + } + + /* If Peripheral ready to accept new data */ + if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) + { + + /* If the suspension flag has been raised and if the processing is not about + to end, suspend processing */ + if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND)) + { + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + + /* Reset SuspendRequest */ + hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE; + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_SUSPENDED; + + return HAL_OK; + } + + /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and + check whether the digest calculation has been triggered */ + if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) + { + /* Call Input data transfer complete call back + (called at the end of each step for HMAC) */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) + { + /* Wait until Peripheral is not busy anymore */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) + { + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + return HAL_TIMEOUT; + } + /* Initialization start for HMAC STEP 2 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */ + __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */ + hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */ + hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */ + hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start + of a new phase */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ + } + else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) + { + /* Wait until Peripheral is not busy anymore */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK) + { + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + return HAL_TIMEOUT; + } + /* Initialization start for HMAC STEP 3 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */ + __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */ + hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */ + hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */ + hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start + of a new phase */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */ + } + else + { + /* Nothing to do */ + } + } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */ + } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/ + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + + +/** + * @brief Write a block of data in HASH Peripheral in interruption mode. + * @param hhash HASH handle. + * @note HASH_Write_Block_Data() is called under interruption by HASH_IT(). + * @retval HAL status + */ +static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash) +{ + uint32_t inputaddr; + uint32_t buffercounter; + uint32_t inputcounter; + uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED; + + /* If there are more than 64 bytes remaining to be entered */ + if (hhash->HashInCount > 64U) + { + inputaddr = (uint32_t)hhash->pHashInBuffPtr; + /* Write the Input block in the Data IN register + (16 32-bit words, or 64 bytes are entered) */ + for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U) + { + HASH->DIN = *(uint32_t *)inputaddr; + inputaddr += 4U; + } + /* If this is the start of input data entering, an additional word + must be entered to start up the HASH processing */ + if (hhash->HashITCounter == 2U) + { + HASH->DIN = *(uint32_t *)inputaddr; + if (hhash->HashInCount >= 68U) + { + /* There are still data waiting to be entered in the Peripheral. + Decrement buffer counter and set pointer to the proper + memory location for the next data entering round. */ + hhash->HashInCount -= 68U; + hhash->pHashInBuffPtr += 68U; + } + else + { + /* All the input buffer has been fed to the HW. */ + hhash->HashInCount = 0U; + } + } + else + { + /* 64 bytes have been entered and there are still some remaining: + Decrement buffer counter and set pointer to the proper + memory location for the next data entering round.*/ + hhash->HashInCount -= 64U; + hhash->pHashInBuffPtr += 64U; + } + } + else + { + /* 64 or less bytes remain to be entered. This is the last + data entering round. */ + + /* Get the buffer address */ + inputaddr = (uint32_t)hhash->pHashInBuffPtr; + /* Get the buffer counter */ + inputcounter = hhash->HashInCount; + /* Disable Interrupts */ + __HAL_HASH_DISABLE_IT(HASH_IT_DINI); + + /* Write the Input block in the Data IN register */ + for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++) + { + HASH->DIN = *(uint32_t *)inputaddr; + inputaddr += 4U; + } + + if (hhash->Accumulation == 1U) + { + /* Field accumulation is set, API only feeds data to the Peripheral and under interruption. + The digest computation will be started when the last buffer data are entered. */ + + /* Reset multi buffers accumulation flag */ + hhash->Accumulation = 0U; + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + /* Call Input data transfer complete call back */ +#if (USE_HAL_HASH_REGISTER_CALLBACKS == 1) + hhash->InCpltCallback(hhash); +#else + HAL_HASH_InCpltCallback(hhash); +#endif /* USE_HAL_HASH_REGISTER_CALLBACKS */ + } + else + { + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + /* Return indication that digest calculation has started: + this return value triggers the call to Input data transfer + complete call back as well as the proper transition from + one step to another in HMAC mode. */ + ret = HASH_DIGEST_CALCULATION_STARTED; + } + /* Reset buffer counter */ + hhash->HashInCount = 0; + } + + /* Return whether or digest calculation has started */ + return ret; +} + +/** + * @brief HMAC processing in polling mode. + * @param hhash HASH handle. + * @param Timeout Timeout value. + * @retval HAL status + */ +static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout) +{ + /* Ensure first that Phase is correct */ + if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2) + && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3)) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_ERROR; + } + + /* HMAC Step 1 processing */ + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) + { + /************************** STEP 1 ******************************************/ + /* Configure the Number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* Check whether or not key entering process has been suspended */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Stop right there and return function status */ + return HAL_OK; + } + + /* No processing suspension at this point: set DCAL bit. */ + __HAL_HASH_START_DIGEST(); + + /* Wait for BUSY flag to be cleared */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Move from Step 1 to Step 2 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; + + } + + /* HMAC Step 2 processing. + After phase check, HMAC_Processing() may + - directly start up from this point in resumption case + if the same Step 2 processing was suspended previously + - or fall through from the Step 1 processing carried out hereabove */ + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) + { + /************************** STEP 2 ******************************************/ + /* Configure the Number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* Check whether or not data entering process has been suspended */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Stop right there and return function status */ + return HAL_OK; + } + + /* No processing suspension at this point: set DCAL bit. */ + __HAL_HASH_START_DIGEST(); + + /* Wait for BUSY flag to be cleared */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Move from Step 2 to Step 3 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; + /* In case Step 1 phase was suspended then resumed, + set again Key input buffers and size before moving to + next step */ + hhash->pHashKeyBuffPtr = hhash->Init.pKey; + hhash->HashKeyCount = hhash->Init.KeySize; + } + + + /* HMAC Step 3 processing. + After phase check, HMAC_Processing() may + - directly start up from this point in resumption case + if the same Step 3 processing was suspended previously + - or fall through from the Step 2 processing carried out hereabove */ + if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3) + { + /************************** STEP 3 ******************************************/ + /* Configure the Number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* Check whether or not key entering process has been suspended */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Stop right there and return function status */ + return HAL_OK; + } + + /* No processing suspension at this point: start the Digest calculation. */ + __HAL_HASH_START_DIGEST(); + + /* Wait for DCIS flag to be set */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read the message digest */ + HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH()); + + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + } + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; +} + + +/** + * @brief Initialize the HASH peripheral, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout, uint32_t Algorithm) +{ + uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ + uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + + + /* Initiate HASH processing in case of start or resumption */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (pOutBuffer == NULL)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* Check if initialization phase has not been already performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); + + /* Configure the number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(Size); + + /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as + input parameters of HASH_WriteData() */ + pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ + Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + } + else if (hhash->Phase == HAL_HASH_PHASE_PROCESS) + { + /* if the Peripheral has already been initialized, two cases are possible */ + + /* Process resumption time ... */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set + to the API input parameters but to those saved beforehand by HASH_WriteData() + when the processing was suspended */ + pInBuffer_tmp = hhash->pHashInBuffPtr; + Size_tmp = hhash->HashInCount; + } + /* ... or multi-buffer HASH processing end */ + else + { + /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as + input parameters of HASH_WriteData() */ + pInBuffer_tmp = pInBuffer; + Size_tmp = Size; + /* Configure the number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(Size); + } + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + } + else + { + /* Phase error */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_ERROR; + } + + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* If the process has not been suspended, carry on to digest calculation */ + if (hhash->State != HAL_HASH_STATE_SUSPENDED) + { + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + + /* Wait for DCIS flag to be set */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read the message digest */ + HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + + } + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; + + } + else + { + return HAL_BUSY; + } +} + + +/** + * @brief If not already done, initialize the HASH peripheral then + * processes pInBuffer. + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) +{ + uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */ + uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + + /* Make sure the input buffer size (in bytes) is a multiple of 4 */ + if ((Size % 4U) != 0U) + { + return HAL_ERROR; + } + + /* Initiate HASH processing in case of start or resumption */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* If resuming the HASH processing */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set + to the API input parameters but to those saved beforehand by HASH_WriteData() + when the processing was suspended */ + pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */ + Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */ + + } + else + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as + input parameters of HASH_WriteData() */ + pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */ + Size_tmp = Size; /* Size_tmp contains the input data size in bytes */ + + /* Check if initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); + } + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + + } + + /* Write input buffer in Data register */ + hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp); + if (hhash->Status != HAL_OK) + { + return hhash->Status; + } + + /* If the process has not been suspended, move the state to Ready */ + if (hhash->State != HAL_HASH_STATE_SUSPENDED) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; + + } + else + { + return HAL_BUSY; + } + + +} + + +/** + * @brief If not already done, initialize the HASH peripheral then + * processes pInBuffer in interruption mode. + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) +{ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + __IO uint32_t inputaddr = (uint32_t) pInBuffer; + uint32_t SizeVar = Size; + + /* Make sure the input buffer size (in bytes) is a multiple of 4 */ + if ((Size % 4U) != 0U) + { + return HAL_ERROR; + } + + /* Initiate HASH processing in case of start or resumption */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* If resuming the HASH processing */ + if (hhash->State == HAL_HASH_STATE_SUSPENDED) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + } + else + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Check if initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); + hhash->HashITCounter = 1; + } + else + { + hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ + } + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + + /* If DINIS is equal to 0 (for example if an incomplete block has been previously + fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. + Therefore, first words are manually entered until DINIS raises, or until there + is not more data to enter. */ + while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U)) + { + + /* Write input data 4 bytes at a time */ + HASH->DIN = *(uint32_t *)inputaddr; + inputaddr += 4U; + SizeVar -= 4U; + } + + /* If DINIS is still not set or if all the data have been fed, stop here */ + if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U)) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_READY; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; + } + + /* otherwise, carry on in interrupt-mode */ + hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data + to be fed to the Peripheral */ + hhash->pHashInBuffPtr = (uint8_t *)inputaddr; /* Points at data which will be fed to the Peripheral at + the next interruption */ + /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain + the information describing where the HASH process is stopped. + These variables are used later on to resume the HASH processing at the + correct location. */ + + } + + /* Set multi buffers accumulation flag */ + hhash->Accumulation = 1U; + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Data Input interrupt */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI); + + /* Return function status */ + return HAL_OK; + + } + else + { + return HAL_BUSY; + } + +} + + + +/** + * @brief Initialize the HASH peripheral, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Algorithm) +{ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + __IO uint32_t inputaddr = (uint32_t) pInBuffer; + uint32_t polling_step = 0U; + uint32_t initialization_skipped = 0U; + uint32_t SizeVar = Size; + + /* If State is ready or suspended, start or resume IT-based HASH processing */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Initialize IT counter */ + hhash->HashITCounter = 1; + + /* Check if initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); + + /* Configure the number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(SizeVar); + + + hhash->HashInCount = SizeVar; /* Counter used to keep track of number of data + to be fed to the Peripheral */ + hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the Peripheral at + the next interruption */ + /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain + the information describing where the HASH process is stopped. + These variables are used later on to resume the HASH processing at the + correct location. */ + + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + } + else + { + initialization_skipped = 1; /* info user later on in case of multi-buffer */ + } + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + + /* If DINIS is equal to 0 (for example if an incomplete block has been previously + fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set. + Therefore, first words are manually entered until DINIS raises. */ + while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U)) + { + polling_step = 1U; /* note that some words are entered before enabling the interrupt */ + + /* Write input data 4 bytes at a time */ + HASH->DIN = *(uint32_t *)inputaddr; + inputaddr += 4U; + SizeVar -= 4U; + } + + if (polling_step == 1U) + { + if (SizeVar == 0U) + { + /* If all the data have been entered at this point, it only remains to + read the digest */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + + /* Start the Digest calculation */ + __HAL_HASH_START_DIGEST(); + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) + { + /* It remains data to enter and the Peripheral is ready to trigger DINIE, + carry on as usual. + Update HashInCount and pHashInBuffPtr accordingly. */ + hhash->HashInCount = SizeVar; + hhash->pHashInBuffPtr = (uint8_t *)inputaddr; + /* Update the configuration of the number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(SizeVar); + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + if (initialization_skipped == 1U) + { + hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */ + } + } + else + { + /* DINIS is not set but it remains a few data to enter (not enough for a full word). + Manually enter the last bytes before enabling DCIE. */ + __HAL_HASH_SET_NBVALIDBITS(SizeVar); + HASH->DIN = *(uint32_t *)inputaddr; + + /* Start the Digest calculation */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */ + __HAL_HASH_START_DIGEST(); + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + } /* if (polling_step == 1) */ + + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_BUSY; + } + +} + + +/** + * @brief Initialize the HASH peripheral then initiate a DMA transfer + * to feed the input buffer to the Peripheral. + * @note If MDMAT bit is set before calling this function (multi-buffer + * HASH processing case), the input buffer size (in bytes) must be + * a multiple of 4 otherwise, the HASH digest computation is corrupted. + * For the processing of the last buffer of the thread, MDMAT bit must + * be reset and the buffer length (in bytes) doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) +{ + uint32_t inputaddr; + uint32_t inputSize; + HAL_StatusTypeDef status ; + HAL_HASH_StateTypeDef State_tmp = hhash->State; + +#if defined (HASH_CR_MDMAT) + /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set + (case of multi-buffer HASH processing) */ + assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size)); +#endif /* MDMA defined*/ + /* If State is ready or suspended, start or resume polling-based HASH processing */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U) || + /* Check phase coherency. Phase must be + either READY (fresh start) + or PROCESS (multi-buffer HASH management) */ + ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash))))) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* If not a resumption case */ + if (hhash->State == HAL_HASH_STATE_READY) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Check if initialization phase has already been performed. + If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the + API is processing a new input data message in case of multi-buffer HASH + computation. */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */ + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT); + + /* Set the phase */ + hhash->Phase = HAL_HASH_PHASE_PROCESS; + } + + /* Configure the Number of valid bits in last word of the message */ + __HAL_HASH_SET_NBVALIDBITS(Size); + + inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */ + inputSize = Size; /* DMA transfer size (in bytes) */ + + /* In case of suspension request, save the starting parameters */ + hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */ + hhash->HashInCount = Size; /* DMA transfer size (in bytes) */ + + } + /* If resumption case */ + else + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Resumption case, inputaddr and inputSize are not set to the API input parameters + but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the + processing was suspended */ + inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */ + inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */ + + } + + /* Set the HASH DMA transfer complete callback */ + hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; + /* Set the DMA error callback */ + hhash->hdmain->XferErrorCallback = HASH_DMAError; + + /* Store number of words already pushed to manage proper DMA processing suspension */ + hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); + + /* Enable the DMA In DMA stream */ + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ + (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \ + (inputSize / 4U))); + + /* Enable DMA requests */ + SET_BIT(HASH->CR, HASH_CR_DMAE); + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + + return status; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Return the computed digest. + * @note The API waits for DCIS to be set then reads the computed digest. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) +{ + + if (hhash->State == HAL_HASH_STATE_READY) + { + /* Check parameter */ + if (pOutBuffer == NULL) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* Change the HASH state to busy */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Wait for DCIS flag to be set */ + if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Read the message digest */ + HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH()); + + /* Change the HASH state to ready */ + hhash->State = HAL_HASH_STATE_READY; + + /* Reset HASH state machine */ + hhash->Phase = HAL_HASH_PHASE_READY; + + /* Process UnLock */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + return HAL_OK; + + } + else + { + return HAL_BUSY; + } + +} + + +/** + * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Timeout Timeout value. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Timeout, uint32_t Algorithm) +{ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + + /* If State is ready or suspended, start or resume polling-based HASH processing */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) + || (pOutBuffer == NULL)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Check if initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ + if (hhash->Init.KeySize > 64U) + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); + } + else + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); + } + /* Set the phase to Step 1 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; + /* Resort to hhash internal fields to feed the Peripheral. + Parameters will be updated in case of suspension to contain the proper + information at resumption time. */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ + hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input + parameter for Step 2 */ + hhash->HashInCount = Size; /* Input data size, HMAC_Processing input + parameter for Step 2 */ + hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process*/ + hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step + 1 and Step 3 */ + hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1 + and Step 3 */ + } + + /* Carry out HMAC processing */ + return HMAC_Processing(hhash, Timeout); + + } + else + { + return HAL_BUSY; + } +} + + + +/** + * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer, + uint32_t Algorithm) +{ + HAL_HASH_StateTypeDef State_tmp = hhash->State; + + /* If State is ready or suspended, start or resume IT-based HASH processing */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) + || (pOutBuffer == NULL)) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Initialize IT counter */ + hhash->HashITCounter = 1; + + /* Check if initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ + if (hhash->Init.KeySize > 64U) + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); + } + else + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); + } + + /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount + to feed the Peripheral whatever the HMAC step. + Lines below are set to start HMAC Step 1 processing where key is entered first. */ + hhash->HashInCount = hhash->Init.KeySize; /* Key size */ + hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */ + + /* Store input and output parameters in handle fields to manage steps transition + or possible HMAC suspension/resumption */ + hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ + hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */ + hhash->HashBuffSize = Size; /* Input message size (in bytes) */ + hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */ + + /* Configure the number of valid bits in last word of the key */ + __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); + + /* Set the phase to Step 1 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; + } + else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)) + { + /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */ + + } + else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) + { + /* Restart IT-based HASH processing after Step 2 suspension */ + + } + else + { + /* Error report as phase incorrect */ + /* Process Unlock */ + __HAL_UNLOCK(hhash); + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + /* Process Unlock */ + __HAL_UNLOCK(hhash); + + /* Enable Interrupts */ + __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI); + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_BUSY; + } + +} + + + +/** + * @brief Initialize the HASH peripheral in HMAC mode then initiate the required + * DMA transfers to feed the key and the input buffer to the Peripheral. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must + * be a multiple of 4 otherwise, the HASH digest computation is corrupted. + * Only the length of the last buffer of the thread doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param Algorithm HASH algorithm. + * @retval HAL status + */ +HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm) +{ + uint32_t inputaddr; + uint32_t inputSize; + HAL_StatusTypeDef status ; + HAL_HASH_StateTypeDef State_tmp = hhash->State; + /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation + is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */ + assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size)); + /* If State is ready or suspended, start or resume DMA-based HASH processing */ + if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED)) + { + /* Check input parameters */ + if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || + /* Check phase coherency. Phase must be + either READY (fresh start) + or one of HMAC PROCESS steps (multi-buffer HASH management) */ + ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash))))) + { + hhash->State = HAL_HASH_STATE_READY; + return HAL_ERROR; + } + + + /* Process Locked */ + __HAL_LOCK(hhash); + + /* If not a case of resumption after suspension */ + if (hhash->State == HAL_HASH_STATE_READY) + { + /* Check whether or not initialization phase has already be performed */ + if (hhash->Phase == HAL_HASH_PHASE_READY) + { + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; +#if defined(HASH_CR_MDMAT) + /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits. + At the same time, ensure MDMAT bit is cleared. */ + if (hhash->Init.KeySize > 64U) + { + MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); + } + else + { + MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); + } +#else + /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */ + if (hhash->Init.KeySize > 64U) + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT); + } + else + { + MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, + Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT); + } +#endif /* HASH_CR_MDMAT*/ + /* Store input aparameters in handle fields to manage steps transition + or possible HMAC suspension/resumption */ + hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */ + hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */ + hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */ + hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */ + hhash->HashBuffSize = Size; /* input data size (in bytes) */ + + /* Set DMA input parameters */ + inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */ + inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */ + + /* Configure the number of valid bits in last word of the key */ + __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); + + /* Set the phase to Step 1 */ + hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1; + + } + else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2) + { + /* Process a new input data message in case of multi-buffer HMAC processing + (this is not a resumption case) */ + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Save input parameters to be able to manage possible suspension/resumption */ + hhash->HashInCount = Size; /* Input message address */ + hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */ + + /* Set DMA input parameters */ + inputaddr = (uint32_t)pInBuffer; /* Input message address */ + inputSize = Size; /* Input message size in bytes */ + + if (hhash->DigestCalculationDisable == RESET) + { + /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */ +#if defined(HASH_CR_MDMAT) + __HAL_HASH_RESET_MDMAT(); +#endif /* HASH_CR_MDMAT*/ + __HAL_HASH_SET_NBVALIDBITS(inputSize); + } + } + else + { + /* Phase not aligned with handle READY state */ + __HAL_UNLOCK(hhash); + /* Return function status */ + return HAL_ERROR; + } + } + else + { + /* Resumption case (phase may be Step 1, 2 or 3) */ + + /* Change the HASH state */ + hhash->State = HAL_HASH_STATE_BUSY; + + /* Set DMA input parameters at resumption location; + inputaddr and inputSize are not set to the API input parameters + but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the + processing was suspended. */ + inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */ + inputSize = hhash->HashInCount; /* Input message size in bytes */ + } + + + /* Set the HASH DMA transfer complete callback */ + hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt; + /* Set the DMA error callback */ + hhash->hdmain->XferErrorCallback = HASH_DMAError; + + /* Store number of words already pushed to manage proper DMA processing suspension */ + hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED(); + + /* Enable the DMA In DMA stream */ + status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \ + (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \ + : (inputSize / 4U))); + + /* Enable DMA requests */ + SET_BIT(HASH->CR, HASH_CR_DMAE); + + /* Process Unlocked */ + __HAL_UNLOCK(hhash); + + /* Return function status */ + if (status != HAL_OK) + { + /* Update HASH state machine to error */ + hhash->State = HAL_HASH_STATE_ERROR; + } + + /* Return function status */ + return status; + } + else + { + return HAL_BUSY; + } +} +/** + * @} + */ + +#endif /* HAL_HASH_MODULE_ENABLED */ + +/** + * @} + */ +#endif /* HASH*/ +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c new file mode 100644 index 0000000..63cb38e --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hash_ex.c @@ -0,0 +1,1040 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hash_ex.c + * @author MCD Application Team + * @brief Extended HASH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the HASH peripheral for SHA-224 and SHA-256 + * algorithms: + * + HASH or HMAC processing in polling mode + * + HASH or HMAC processing in interrupt mode + * + HASH or HMAC processing in DMA mode + * Additionally, this file provides functions to manage HMAC + * multi-buffer DMA-based processing for MD-5, SHA-1, SHA-224 + * and SHA-256. + * + * + ****************************************************************************** + * @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 + =============================================================================== + ##### HASH peripheral extended features ##### + =============================================================================== + [..] + The SHA-224 and SHA-256 HASH and HMAC processing can be carried out exactly + the same way as for SHA-1 or MD-5 algorithms. + (#) Three modes are available. + (##) Polling mode: processing APIs are blocking functions + i.e. they process the data and wait till the digest computation is finished, + e.g. HAL_HASHEx_xxx_Start() + (##) Interrupt mode: processing APIs are not blocking functions + i.e. they process the data under interrupt, + e.g. HAL_HASHEx_xxx_Start_IT() + (##) DMA mode: processing APIs are not blocking functions and the CPU is + not used for data transfer i.e. the data transfer is ensured by DMA, + e.g. HAL_HASHEx_xxx_Start_DMA(). Note that in DMA mode, a call to + HAL_HASHEx_xxx_Finish() is then required to retrieve the digest. + + (#)Multi-buffer processing is possible in polling, interrupt and DMA modes. + (##) In polling mode, only multi-buffer HASH processing is possible. + API HAL_HASHEx_xxx_Accumulate() must be called for each input buffer, except for the last one. + User must resort to HAL_HASHEx_xxx_Accumulate_End() to enter the last one and retrieve as + well the computed digest. + + (##) In interrupt mode, API HAL_HASHEx_xxx_Accumulate_IT() must be called for each input buffer, + except for the last one. + User must resort to HAL_HASHEx_xxx_Accumulate_End_IT() to enter the last one and retrieve as + well the computed digest. + + (##) In DMA mode, multi-buffer HASH and HMAC processing are possible. + + (+++) HASH processing: once initialization is done, MDMAT bit must be set through + __HAL_HASH_SET_MDMAT() macro. + From that point, each buffer can be fed to the Peripheral through HAL_HASHEx_xxx_Start_DMA() API. + Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT() + macro then wrap-up the HASH processing in feeding the last input buffer through the + same API HAL_HASHEx_xxx_Start_DMA(). The digest can then be retrieved with a call to + API HAL_HASHEx_xxx_Finish(). + + (+++) HMAC processing (MD-5, SHA-1, SHA-224 and SHA-256 must all resort to + extended functions): after initialization, the key and the first input buffer are entered + in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and + starts step 2. + The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this + point, the HMAC processing is still carrying out step 2. + Then, step 2 for the last input buffer and step 3 are carried out by a single call + to HAL_HMACEx_xxx_Step2_3_DMA(). + + The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish() for + MD-5 and SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 and SHA-256. + + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + + + + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined (HASH) + +/** @defgroup HASHEx HASHEx + * @brief HASH HAL extended module driver. + * @{ + */ +#ifdef HAL_HASH_MODULE_ENABLED +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +#if defined (HASH_CR_MDMAT) + +/** @defgroup HASHEx_Exported_Functions HASH Extended Exported Functions + * @{ + */ + +/** @defgroup HASHEx_Exported_Functions_Group1 HASH extended processing functions in polling mode + * @brief HASH extended processing functions using polling mode. + * +@verbatim + =============================================================================== + ##### Polling mode HASH extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in polling mode + the hash value using one of the following algorithms: + (+) SHA224 + (++) HAL_HASHEx_SHA224_Start() + (++) HAL_HASHEx_SHA224_Accmlt() + (++) HAL_HASHEx_SHA224_Accmlt_End() + (+) SHA256 + (++) HAL_HASHEx_SHA256_Start() + (++) HAL_HASHEx_SHA256_Accmlt() + (++) HAL_HASHEx_SHA256_Accmlt_End() + + [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start(). + + [..] In case of multi-buffer HASH processing (a single digest is computed while + several buffers are fed to the Peripheral), the user can resort to successive calls + to HAL_HASHEx_xxx_Accumulate() and wrap-up the digest computation by a call + to HAL_HASHEx_xxx_Accumulate_End(). + +@endverbatim + * @{ + */ + + +/** + * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief If not already done, initialize the HASH peripheral in SHA224 mode then + * processes pInBuffer. + * @note Consecutive calls to HAL_HASHEx_SHA224_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASHEx_SHA224_Accmlt_End(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA224_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASHEx_SHA224_Accmlt_End() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA224_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief If not already done, initialize the HASH peripheral in SHA256 mode then + * processes pInBuffer. + * @note Consecutive calls to HAL_HASHEx_SHA256_Accmlt() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASHEx_SHA256_Accmlt_End(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note Digest is not retrieved by this API, user must resort to HAL_HASHEx_SHA256_Accmlt_End() + * to read it, feeding at the same time the last input buffer to the Peripheral. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASHEx_SHA256_Accmlt_End() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA256_Accmlt() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @param Timeout Timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); +} + +/** + * @} + */ + +/** @defgroup HASHEx_Exported_Functions_Group2 HASH extended processing functions in interrupt mode + * @brief HASH extended processing functions using interrupt mode. + * +@verbatim + =============================================================================== + ##### Interruption mode HASH extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in interrupt mode + the hash value using one of the following algorithms: + (+) SHA224 + (++) HAL_HASHEx_SHA224_Start_IT() + (++) HAL_HASHEx_SHA224_Accmlt_IT() + (++) HAL_HASHEx_SHA224_Accmlt_End_IT() + (+) SHA256 + (++) HAL_HASHEx_SHA256_Start_IT() + (++) HAL_HASHEx_SHA256_Accmlt_IT() + (++) HAL_HASHEx_SHA256_Accmlt_End_IT() + +@endverbatim + * @{ + */ + + +/** + * @brief Initialize the HASH peripheral in SHA224 mode, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief If not already done, initialize the HASH peripheral in SHA224 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASHEx_SHA224_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASHEx_SHA224_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASHEx_SHA224_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA224_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Initialize the HASH peripheral in SHA256 mode, next process pInBuffer then + * read the computed digest in interruption mode. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief If not already done, initialize the HASH peripheral in SHA256 mode then + * processes pInBuffer in interruption mode. + * @note Consecutive calls to HAL_HASHEx_SHA256_Accmlt_IT() can be used to feed + * several input buffers back-to-back to the Peripheral that will yield a single + * HASH signature once all buffers have been entered. Wrap-up of input + * buffers feeding and retrieval of digest is done by a call to + * HAL_HASHEx_SHA256_Accmlt_End_IT(). + * @note Field hhash->Phase of HASH handle is tested to check whether or not + * the Peripheral has already been initialized. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. Only HAL_HASHEx_SHA256_Accmlt_End_IT() is able + * to manage the ending buffer with a length in bytes not a multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes, must be a multiple of 4. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief End computation of a single HASH signature after several calls to HAL_HASHEx_SHA256_Accmlt_IT() API. + * @note Digest is available in pOutBuffer. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA256); +} + +/** + * @} + */ + +/** @defgroup HASHEx_Exported_Functions_Group3 HASH extended processing functions in DMA mode + * @brief HASH extended processing functions using DMA mode. + * +@verbatim + =============================================================================== + ##### DMA mode HASH extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in DMA mode + the hash value using one of the following algorithms: + (+) SHA224 + (++) HAL_HASHEx_SHA224_Start_DMA() + (++) HAL_HASHEx_SHA224_Finish() + (+) SHA256 + (++) HAL_HASHEx_SHA256_Start_DMA() + (++) HAL_HASHEx_SHA256_Finish() + + [..] When resorting to DMA mode to enter the data in the Peripheral, user must resort + to HAL_HASHEx_xxx_Start_DMA() then read the resulting digest with + HAL_HASHEx_xxx_Finish(). + + [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before + the successive calls to HAL_HASHEx_xxx_Start_DMA(). Then, MDMAT bit needs to be + reset before the last call to HAL_HASHEx_xxx_Start_DMA(). Digest is finally + retrieved thanks to HAL_HASHEx_xxx_Finish(). + +@endverbatim + * @{ + */ + + + + +/** + * @brief Initialize the HASH peripheral in SHA224 mode then initiate a DMA transfer + * to feed the input buffer to the Peripheral. + * @note Once the DMA transfer is finished, HAL_HASHEx_SHA224_Finish() API must + * be called to retrieve the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Return the computed digest in SHA224 mode. + * @note The API waits for DCIS to be set then reads the computed digest. + * @note HAL_HASHEx_SHA224_Finish() can be used as well to retrieve the digest in + * HMAC SHA224 mode. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA224_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Finish(hhash, pOutBuffer, Timeout); +} + +/** + * @brief Initialize the HASH peripheral in SHA256 mode then initiate a DMA transfer + * to feed the input buffer to the Peripheral. + * @note Once the DMA transfer is finished, HAL_HASHEx_SHA256_Finish() API must + * be called to retrieve the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief Return the computed digest in SHA256 mode. + * @note The API waits for DCIS to be set then reads the computed digest. + * @note HAL_HASHEx_SHA256_Finish() can be used as well to retrieve the digest in + * HMAC SHA256 mode. + * @param hhash HASH handle. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HASHEx_SHA256_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HASH_Finish(hhash, pOutBuffer, Timeout); +} + +/** + * @} + */ + +/** @defgroup HASHEx_Exported_Functions_Group4 HMAC extended processing functions in polling mode + * @brief HMAC extended processing functions using polling mode. + * +@verbatim + =============================================================================== + ##### Polling mode HMAC extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in polling mode + the HMAC value using one of the following algorithms: + (+) SHA224 + (++) HAL_HMACEx_SHA224_Start() + (+) SHA256 + (++) HAL_HMACEx_SHA256_Start() + +@endverbatim + * @{ + */ + + + +/** + * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then + * read the computed digest. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @param Timeout Timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer, uint32_t Timeout) +{ + return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA256); +} + +/** + * @} + */ + + +/** @defgroup HASHEx_Exported_Functions_Group5 HMAC extended processing functions in interrupt mode + * @brief HMAC extended processing functions using interruption mode. + * +@verbatim + =============================================================================== + ##### Interrupt mode HMAC extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in interrupt mode + the HMAC value using one of the following algorithms: + (+) SHA224 + (++) HAL_HMACEx_SHA224_Start_IT() + (+) SHA256 + (++) HAL_HMACEx_SHA256_Start_IT() + +@endverbatim + * @{ + */ + + + +/** + * @brief Initialize the HASH peripheral in HMAC SHA224 mode, next process pInBuffer then + * read the computed digest in interrupt mode. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 28 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Initialize the HASH peripheral in HMAC SHA256 mode, next process pInBuffer then + * read the computed digest in interrupt mode. + * @note Digest is available in pOutBuffer. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @param pOutBuffer pointer to the computed digest. Digest size is 32 bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, + uint8_t *pOutBuffer) +{ + return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA256); +} + + + + +/** + * @} + */ + + +/** @defgroup HASHEx_Exported_Functions_Group6 HMAC extended processing functions in DMA mode + * @brief HMAC extended processing functions using DMA mode. + * +@verbatim + =============================================================================== + ##### DMA mode HMAC extended processing functions ##### + =============================================================================== + [..] This section provides functions allowing to calculate in DMA mode + the HMAC value using one of the following algorithms: + (+) SHA224 + (++) HAL_HMACEx_SHA224_Start_DMA() + (+) SHA256 + (++) HAL_HMACEx_SHA256_Start_DMA() + + [..] When resorting to DMA mode to enter the data in the Peripheral for HMAC processing, + user must resort to HAL_HMACEx_xxx_Start_DMA() then read the resulting digest + with HAL_HASHEx_xxx_Finish(). + + +@endverbatim + * @{ + */ + + + +/** + * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required + * DMA transfers to feed the key and the input buffer to the Peripheral. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA224_Finish() API must be called to retrieve + * the computed digest. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note If MDMAT bit is set before calling this function (multi-buffer + * HASH processing case), the input buffer size (in bytes) must be + * a multiple of 4 otherwise, the HASH digest computation is corrupted. + * For the processing of the last buffer of the thread, MDMAT bit must + * be reset and the buffer length (in bytes) doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief Initialize the HASH peripheral in HMAC SHA224 mode then initiate the required + * DMA transfers to feed the key and the input buffer to the Peripheral. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve + * the computed digest. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note If MDMAT bit is set before calling this function (multi-buffer + * HASH processing case), the input buffer size (in bytes) must be + * a multiple of 4 otherwise, the HASH digest computation is corrupted. + * For the processing of the last buffer of the thread, MDMAT bit must + * be reset and the buffer length (in bytes) doesn't have to be a + * multiple of 4. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (buffer to be hashed). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + + +/** + * @} + */ + +/** @defgroup HASHEx_Exported_Functions_Group7 Multi-buffer HMAC extended processing functions in DMA mode + * @brief HMAC extended processing functions in multi-buffer DMA mode. + * +@verbatim + =============================================================================== + ##### Multi-buffer DMA mode HMAC extended processing functions ##### + =============================================================================== + [..] This section provides functions to manage HMAC multi-buffer + DMA-based processing for MD5, SHA1, SHA224 and SHA256 algorithms. + (+) MD5 + (++) HAL_HMACEx_MD5_Step1_2_DMA() + (++) HAL_HMACEx_MD5_Step2_DMA() + (++) HAL_HMACEx_MD5_Step2_3_DMA() + (+) SHA1 + (++) HAL_HMACEx_SHA1_Step1_2_DMA() + (++) HAL_HMACEx_SHA1_Step2_DMA() + (++) HAL_HMACEx_SHA1_Step2_3_DMA() + + (+) SHA256 + (++) HAL_HMACEx_SHA224_Step1_2_DMA() + (++) HAL_HMACEx_SHA224_Step2_DMA() + (++) HAL_HMACEx_SHA224_Step2_3_DMA() + (+) SHA256 + (++) HAL_HMACEx_SHA256_Step1_2_DMA() + (++) HAL_HMACEx_SHA256_Step2_DMA() + (++) HAL_HMACEx_SHA256_Step2_3_DMA() + + [..] User must first start-up the multi-buffer DMA-based HMAC computation in + calling HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and + intiates step 2 with the first input buffer. + + [..] The following buffers are next fed to the Peripheral with a call to the API + HAL_HMACEx_xxx_Step2_DMA(). There may be several consecutive calls + to this API. + + [..] Multi-buffer DMA-based HMAC computation is wrapped up by a call to + HAL_HMACEx_xxx_Step2_3_DMA(). This finishes step 2 in feeding the last input + buffer to the Peripheral then carries out step 3. + + [..] Digest is retrieved by a call to HAL_HASH_xxx_Finish() for MD-5 or + SHA-1, to HAL_HASHEx_xxx_Finish() for SHA-224 or SHA-256. + + [..] If only two buffers need to be consecutively processed, a call to + HAL_HMACEx_xxx_Step1_2_DMA() followed by a call to HAL_HMACEx_xxx_Step2_3_DMA() + is sufficient. + +@endverbatim + * @{ + */ + +/** + * @brief MD5 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. + * @note Step 1 consists in writing the inner hash function key in the Peripheral, + * step 2 consists in writing the message text. + * @note The API carries out the HMAC step 1 then starts step 2 with + * the first buffer entered to the Peripheral. DCAL bit is not automatically set after + * the message buffer feeding, allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_MD5_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = SET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief MD5 HMAC step 2 in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral. + * @note The API carries on the HMAC step 2, applied to the buffer entered as input + * parameter. DCAL bit is not automatically set after the message buffer feeding, + * allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + if (hhash->DigestCalculationDisable != SET) + { + return HAL_ERROR; + } + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + +/** + * @brief MD5 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral, + * step 3 consists in writing the outer hash function key. + * @note The API wraps up the HMAC step 2 in processing the buffer entered as input + * parameter (the input buffer must be the last one of the multi-buffer thread) + * then carries out HMAC step 3. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve + * the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_MD5_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = RESET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5); +} + + +/** + * @brief SHA1 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. + * @note Step 1 consists in writing the inner hash function key in the Peripheral, + * step 2 consists in writing the message text. + * @note The API carries out the HMAC step 1 then starts step 2 with + * the first buffer entered to the Peripheral. DCAL bit is not automatically set after + * the message buffer feeding, allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = SET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief SHA1 HMAC step 2 in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral. + * @note The API carries on the HMAC step 2, applied to the buffer entered as input + * parameter. DCAL bit is not automatically set after the message buffer feeding, + * allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + if (hhash->DigestCalculationDisable != SET) + { + return HAL_ERROR; + } + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief SHA1 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral, + * step 3 consists in writing the outer hash function key. + * @note The API wraps up the HMAC step 2 in processing the buffer entered as input + * parameter (the input buffer must be the last one of the multi-buffer thread) + * then carries out HMAC step 3. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve + * the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA1_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = RESET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1); +} + +/** + * @brief SHA224 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. + * @note Step 1 consists in writing the inner hash function key in the Peripheral, + * step 2 consists in writing the message text. + * @note The API carries out the HMAC step 1 then starts step 2 with + * the first buffer entered to the Peripheral. DCAL bit is not automatically set after + * the message buffer feeding, allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = SET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief SHA224 HMAC step 2 in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral. + * @note The API carries on the HMAC step 2, applied to the buffer entered as input + * parameter. DCAL bit is not automatically set after the message buffer feeding, + * allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + if (hhash->DigestCalculationDisable != SET) + { + return HAL_ERROR; + } + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief SHA224 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral, + * step 3 consists in writing the outer hash function key. + * @note The API wraps up the HMAC step 2 in processing the buffer entered as input + * parameter (the input buffer must be the last one of the multi-buffer thread) + * then carries out HMAC step 3. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve + * the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA224_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = RESET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA224); +} + +/** + * @brief SHA256 HMAC step 1 completion and step 2 start in multi-buffer DMA mode. + * @note Step 1 consists in writing the inner hash function key in the Peripheral, + * step 2 consists in writing the message text. + * @note The API carries out the HMAC step 1 then starts step 2 with + * the first buffer entered to the Peripheral. DCAL bit is not automatically set after + * the message buffer feeding, allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step1_2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = SET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief SHA256 HMAC step 2 in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral. + * @note The API carries on the HMAC step 2, applied to the buffer entered as input + * parameter. DCAL bit is not automatically set after the message buffer feeding, + * allowing other messages DMA transfers to occur. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the + * HASH digest computation is corrupted. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + if (hhash->DigestCalculationDisable != SET) + { + return HAL_ERROR; + } + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @brief SHA256 HMAC step 2 wrap-up and step 3 completion in multi-buffer DMA mode. + * @note Step 2 consists in writing the message text in the Peripheral, + * step 3 consists in writing the outer hash function key. + * @note The API wraps up the HMAC step 2 in processing the buffer entered as input + * parameter (the input buffer must be the last one of the multi-buffer thread) + * then carries out HMAC step 3. + * @note Same key is used for the inner and the outer hash functions; pointer to key and + * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize. + * @note Once the DMA transfers are finished (indicated by hhash->State set back + * to HAL_HASH_STATE_READY), HAL_HASHEx_SHA256_Finish() API must be called to retrieve + * the computed digest. + * @param hhash HASH handle. + * @param pInBuffer pointer to the input buffer (message buffer). + * @param Size length of the input buffer in bytes. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HMACEx_SHA256_Step2_3_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size) +{ + hhash->DigestCalculationDisable = RESET; + return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA256); +} + +/** + * @} + */ + +#endif /* MDMA defined*/ +/** + * @} + */ +#endif /* HAL_HASH_MODULE_ENABLED */ + +/** + * @} + */ +#endif /* HASH*/ +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c new file mode 100644 index 0000000..c7c5b70 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_hcd.c @@ -0,0 +1,1728 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_hcd.c + * @author MCD Application Team + * @brief HCD HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the USB Peripheral Controller: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State 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 ##### + ============================================================================== + [..] + (#)Declare a HCD_HandleTypeDef handle structure, for example: + HCD_HandleTypeDef hhcd; + + (#)Fill parameters of Init structure in HCD handle + + (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...) + + (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API: + (##) Enable the HCD/USB Low Level interface clock using the following macros + (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode) + (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode) + + (##) Initialize the related GPIO clocks + (##) Configure HCD pin-out + (##) Configure HCD NVIC interrupt + + (#)Associate the Upper USB Host stack to the HAL HCD Driver: + (##) hhcd.pData = phost; + + (#)Enable HCD transmission and reception: + (##) HAL_HCD_Start(); + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_HCD_MODULE_ENABLED +#if defined (USB_OTG_FS) || defined (USB_OTG_HS) + +/** @defgroup HCD HCD + * @brief HCD HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup HCD_Private_Functions HCD Private Functions + * @{ + */ +static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum); +static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd); +static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup HCD_Exported_Functions HCD Exported Functions + * @{ + */ + +/** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the host driver. + * @param hhcd HCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx; + + /* Check the HCD handle allocation */ + if (hhcd == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance)); + + USBx = hhcd->Instance; + + if (hhcd->State == HAL_HCD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hhcd->Lock = HAL_UNLOCKED; + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->SOFCallback = HAL_HCD_SOF_Callback; + hhcd->ConnectCallback = HAL_HCD_Connect_Callback; + hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback; + hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback; + hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback; + hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; + + if (hhcd->MspInitCallback == NULL) + { + hhcd->MspInitCallback = HAL_HCD_MspInit; + } + + /* Init the low level hardware */ + hhcd->MspInitCallback(hhcd); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + HAL_HCD_MspInit(hhcd); +#endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */ + } + + hhcd->State = HAL_HCD_STATE_BUSY; + + /* Disable DMA mode for FS instance */ + if ((USBx->CID & (0x1U << 8)) == 0U) + { + hhcd->Init.dma_enable = 0U; + } + + /* Disable the Interrupts */ + __HAL_HCD_DISABLE(hhcd); + + /* Init the Core (common init.) */ + (void)USB_CoreInit(hhcd->Instance, hhcd->Init); + + /* Force Host Mode*/ + (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE); + + /* Init Host */ + (void)USB_HostInit(hhcd->Instance, hhcd->Init); + + hhcd->State = HAL_HCD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Initialize a host channel. + * @param hhcd HCD handle + * @param ch_num Channel number. + * This parameter can be a value from 1 to 15 + * @param epnum Endpoint number. + * This parameter can be a value from 1 to 15 + * @param dev_address Current device address + * This parameter can be a value from 0 to 255 + * @param speed Current device speed. + * This parameter can be one of these values: + * HCD_DEVICE_SPEED_HIGH: High speed mode, + * HCD_DEVICE_SPEED_FULL: Full speed mode, + * HCD_DEVICE_SPEED_LOW: Low speed mode + * @param ep_type Endpoint Type. + * This parameter can be one of these values: + * EP_TYPE_CTRL: Control type, + * EP_TYPE_ISOC: Isochronous type, + * EP_TYPE_BULK: Bulk type, + * EP_TYPE_INTR: Interrupt type + * @param mps Max Packet Size. + * This parameter can be a value from 0 to32K + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, + uint8_t ch_num, + uint8_t epnum, + uint8_t dev_address, + uint8_t speed, + uint8_t ep_type, + uint16_t mps) +{ + HAL_StatusTypeDef status; + + __HAL_LOCK(hhcd); + hhcd->hc[ch_num].do_ping = 0U; + hhcd->hc[ch_num].dev_addr = dev_address; + hhcd->hc[ch_num].max_packet = mps; + hhcd->hc[ch_num].ch_num = ch_num; + hhcd->hc[ch_num].ep_type = ep_type; + hhcd->hc[ch_num].ep_num = epnum & 0x7FU; + + if ((epnum & 0x80U) == 0x80U) + { + hhcd->hc[ch_num].ep_is_in = 1U; + } + else + { + hhcd->hc[ch_num].ep_is_in = 0U; + } + + hhcd->hc[ch_num].speed = speed; + + status = USB_HC_Init(hhcd->Instance, + ch_num, + epnum, + dev_address, + speed, + ep_type, + mps); + __HAL_UNLOCK(hhcd); + + return status; +} + +/** + * @brief Halt a host channel. + * @param hhcd HCD handle + * @param ch_num Channel number. + * This parameter can be a value from 1 to 15 + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num) +{ + HAL_StatusTypeDef status = HAL_OK; + + __HAL_LOCK(hhcd); + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_UNLOCK(hhcd); + + return status; +} + +/** + * @brief DeInitialize the host driver. + * @param hhcd HCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd) +{ + /* Check the HCD handle allocation */ + if (hhcd == NULL) + { + return HAL_ERROR; + } + + hhcd->State = HAL_HCD_STATE_BUSY; + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + if (hhcd->MspDeInitCallback == NULL) + { + hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware */ + hhcd->MspDeInitCallback(hhcd); +#else + /* DeInit the low level hardware: CLOCK, NVIC.*/ + HAL_HCD_MspDeInit(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + + __HAL_HCD_DISABLE(hhcd); + + hhcd->State = HAL_HCD_STATE_RESET; + + return HAL_OK; +} + +/** + * @brief Initialize the HCD MSP. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the HCD MSP. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions + * @brief HCD IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to manage the USB Host Data + Transfer + +@endverbatim + * @{ + */ + +/** + * @brief Submit a new URB for processing. + * @param hhcd HCD handle + * @param ch_num Channel number. + * This parameter can be a value from 1 to 15 + * @param direction Channel number. + * This parameter can be one of these values: + * 0 : Output / 1 : Input + * @param ep_type Endpoint Type. + * This parameter can be one of these values: + * EP_TYPE_CTRL: Control type/ + * EP_TYPE_ISOC: Isochronous type/ + * EP_TYPE_BULK: Bulk type/ + * EP_TYPE_INTR: Interrupt type/ + * @param token Endpoint Type. + * This parameter can be one of these values: + * 0: HC_PID_SETUP / 1: HC_PID_DATA1 + * @param pbuff pointer to URB data + * @param length Length of URB data + * @param do_ping activate do ping protocol (for high speed only). + * This parameter can be one of these values: + * 0 : do ping inactive / 1 : do ping active + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd, + uint8_t ch_num, + uint8_t direction, + uint8_t ep_type, + uint8_t token, + uint8_t *pbuff, + uint16_t length, + uint8_t do_ping) +{ + hhcd->hc[ch_num].ep_is_in = direction; + hhcd->hc[ch_num].ep_type = ep_type; + + if (token == 0U) + { + hhcd->hc[ch_num].data_pid = HC_PID_SETUP; + hhcd->hc[ch_num].do_ping = do_ping; + } + else + { + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + + /* Manage Data Toggle */ + switch (ep_type) + { + case EP_TYPE_CTRL: + if ((token == 1U) && (direction == 0U)) /*send data */ + { + if (length == 0U) + { + /* For Status OUT stage, Length==0, Status Out PID = 1 */ + hhcd->hc[ch_num].toggle_out = 1U; + } + + /* Set the Data Toggle bit as per the Flag */ + if (hhcd->hc[ch_num].toggle_out == 0U) + { + /* Put the PID 0 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + } + else + { + /* Put the PID 1 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + } + break; + + case EP_TYPE_BULK: + if (direction == 0U) + { + /* Set the Data Toggle bit as per the Flag */ + if (hhcd->hc[ch_num].toggle_out == 0U) + { + /* Put the PID 0 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + } + else + { + /* Put the PID 1 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + } + else + { + if (hhcd->hc[ch_num].toggle_in == 0U) + { + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + } + else + { + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + } + + break; + case EP_TYPE_INTR: + if (direction == 0U) + { + /* Set the Data Toggle bit as per the Flag */ + if (hhcd->hc[ch_num].toggle_out == 0U) + { + /* Put the PID 0 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + } + else + { + /* Put the PID 1 */ + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + } + else + { + if (hhcd->hc[ch_num].toggle_in == 0U) + { + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + } + else + { + hhcd->hc[ch_num].data_pid = HC_PID_DATA1; + } + } + break; + + case EP_TYPE_ISOC: + hhcd->hc[ch_num].data_pid = HC_PID_DATA0; + break; + + default: + break; + } + + hhcd->hc[ch_num].xfer_buff = pbuff; + hhcd->hc[ch_num].xfer_len = length; + hhcd->hc[ch_num].urb_state = URB_IDLE; + hhcd->hc[ch_num].xfer_count = 0U; + hhcd->hc[ch_num].ch_num = ch_num; + hhcd->hc[ch_num].state = HC_IDLE; + + return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable); +} + +/** + * @brief Handle HCD interrupt request. + * @param hhcd HCD handle + * @retval None + */ +void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t USBx_BASE = (uint32_t)USBx; + uint32_t i; + uint32_t interrupt; + + /* Ensure that we are in device mode */ + if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST) + { + /* Avoid spurious interrupt */ + if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) + { + return; + } + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) + { + /* Incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); + } + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR)) + { + /* Incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR); + } + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE)) + { + /* Incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE); + } + + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS)) + { + /* Incorrect mode, acknowledge the interrupt */ + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS); + } + + /* Handle Host Disconnect Interrupts */ + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT)) + { + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT); + + if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U) + { + /* Flush USB Fifo */ + (void)USB_FlushTxFifo(USBx, 0x10U); + (void)USB_FlushRxFifo(USBx); + + /* Restore FS Clock */ + (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ); + + /* Handle Host Port Disconnect Interrupt */ +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->DisconnectCallback(hhcd); +#else + HAL_HCD_Disconnect_Callback(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + } + + /* Handle Host Port Interrupts */ + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT)) + { + HCD_Port_IRQHandler(hhcd); + } + + /* Handle Host SOF Interrupt */ + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF)) + { +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->SOFCallback(hhcd); +#else + HAL_HCD_SOF_Callback(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF); + } + + /* Handle Rx Queue Level Interrupts */ + if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U) + { + USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + + HCD_RXQLVL_IRQHandler(hhcd); + + USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); + } + + /* Handle Host channel Interrupt */ + if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT)) + { + interrupt = USB_HC_ReadInterrupt(hhcd->Instance); + for (i = 0U; i < hhcd->Init.Host_channels; i++) + { + if ((interrupt & (1UL << (i & 0xFU))) != 0U) + { + if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR) + { + HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i); + } + else + { + HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i); + } + } + } + __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT); + } + } +} + + +/** + * @brief Handles HCD Wakeup interrupt request. + * @param hhcd HCD handle + * @retval HAL status + */ +void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + UNUSED(hhcd); +} + + +/** + * @brief SOF callback. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_SOF_Callback could be implemented in the user file + */ +} + +/** + * @brief Connection Event callback. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_Connect_Callback could be implemented in the user file + */ +} + +/** + * @brief Disconnection Event callback. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_Disconnect_Callback could be implemented in the user file + */ +} + +/** + * @brief Port Enabled Event callback. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_Disconnect_Callback could be implemented in the user file + */ +} + +/** + * @brief Port Disabled Event callback. + * @param hhcd HCD handle + * @retval None + */ +__weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_Disconnect_Callback could be implemented in the user file + */ +} + +/** + * @brief Notify URB state change callback. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @param urb_state: + * This parameter can be one of these values: + * URB_IDLE/ + * URB_DONE/ + * URB_NOTREADY/ + * URB_NYET/ + * URB_ERROR/ + * URB_STALL/ + * @retval None + */ +__weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hhcd); + UNUSED(chnum); + UNUSED(urb_state); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file + */ +} + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User USB HCD Callback + * To be used instead of the weak predefined callback + * @param hhcd USB HCD handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID + * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID + * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID + * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID + * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID + * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID + * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd, + HAL_HCD_CallbackIDTypeDef CallbackID, + pHCD_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hhcd); + + if (hhcd->State == HAL_HCD_STATE_READY) + { + switch (CallbackID) + { + case HAL_HCD_SOF_CB_ID : + hhcd->SOFCallback = pCallback; + break; + + case HAL_HCD_CONNECT_CB_ID : + hhcd->ConnectCallback = pCallback; + break; + + case HAL_HCD_DISCONNECT_CB_ID : + hhcd->DisconnectCallback = pCallback; + break; + + case HAL_HCD_PORT_ENABLED_CB_ID : + hhcd->PortEnabledCallback = pCallback; + break; + + case HAL_HCD_PORT_DISABLED_CB_ID : + hhcd->PortDisabledCallback = pCallback; + break; + + case HAL_HCD_MSPINIT_CB_ID : + hhcd->MspInitCallback = pCallback; + break; + + case HAL_HCD_MSPDEINIT_CB_ID : + hhcd->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hhcd->State == HAL_HCD_STATE_RESET) + { + switch (CallbackID) + { + case HAL_HCD_MSPINIT_CB_ID : + hhcd->MspInitCallback = pCallback; + break; + + case HAL_HCD_MSPDEINIT_CB_ID : + hhcd->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhcd); + return status; +} + +/** + * @brief Unregister an USB HCD Callback + * USB HCD callback is redirected to the weak predefined callback + * @param hhcd USB HCD handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID + * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID + * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID + * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID + * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID + * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID + * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hhcd); + + /* Setup Legacy weak Callbacks */ + if (hhcd->State == HAL_HCD_STATE_READY) + { + switch (CallbackID) + { + case HAL_HCD_SOF_CB_ID : + hhcd->SOFCallback = HAL_HCD_SOF_Callback; + break; + + case HAL_HCD_CONNECT_CB_ID : + hhcd->ConnectCallback = HAL_HCD_Connect_Callback; + break; + + case HAL_HCD_DISCONNECT_CB_ID : + hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback; + break; + + case HAL_HCD_PORT_ENABLED_CB_ID : + hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback; + break; + + case HAL_HCD_PORT_DISABLED_CB_ID : + hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback; + break; + + case HAL_HCD_MSPINIT_CB_ID : + hhcd->MspInitCallback = HAL_HCD_MspInit; + break; + + case HAL_HCD_MSPDEINIT_CB_ID : + hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; + break; + + default : + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hhcd->State == HAL_HCD_STATE_RESET) + { + switch (CallbackID) + { + case HAL_HCD_MSPINIT_CB_ID : + hhcd->MspInitCallback = HAL_HCD_MspInit; + break; + + case HAL_HCD_MSPDEINIT_CB_ID : + hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; + break; + + default : + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhcd); + return status; +} + +/** + * @brief Register USB HCD Host Channel Notify URB Change Callback + * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback + * @param hhcd HCD handle + * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd, + pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hhcd); + + if (hhcd->State == HAL_HCD_STATE_READY) + { + hhcd->HC_NotifyURBChangeCallback = pCallback; + } + else + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhcd); + + return status; +} + +/** + * @brief Unregister the USB HCD Host Channel Notify URB Change Callback + * USB HCD Host Channel Notify URB Change Callback is redirected + * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback + * @param hhcd HCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hhcd); + + if (hhcd->State == HAL_HCD_STATE_READY) + { + hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */ + } + else + { + /* Update the error code */ + hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hhcd); + + return status; +} +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions + * @brief Management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the HCD data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Start the host driver. + * @param hhcd HCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd) +{ + __HAL_LOCK(hhcd); + /* Enable port power */ + (void)USB_DriveVbus(hhcd->Instance, 1U); + + /* Enable global interrupt */ + __HAL_HCD_ENABLE(hhcd); + __HAL_UNLOCK(hhcd); + + return HAL_OK; +} + +/** + * @brief Stop the host driver. + * @param hhcd HCD handle + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd) +{ + __HAL_LOCK(hhcd); + (void)USB_StopHost(hhcd->Instance); + __HAL_UNLOCK(hhcd); + + return HAL_OK; +} + +/** + * @brief Reset the host port. + * @param hhcd HCD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd) +{ + return (USB_ResetPort(hhcd->Instance)); +} + +/** + * @} + */ + +/** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the HCD handle state. + * @param hhcd HCD handle + * @retval HAL state + */ +HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd) +{ + return hhcd->State; +} + +/** + * @brief Return URB state for a channel. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @retval URB state. + * This parameter can be one of these values: + * URB_IDLE/ + * URB_DONE/ + * URB_NOTREADY/ + * URB_NYET/ + * URB_ERROR/ + * URB_STALL + */ +HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + return hhcd->hc[chnum].urb_state; +} + + +/** + * @brief Return the last host transfer size. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @retval last transfer size in byte + */ +uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + return hhcd->hc[chnum].xfer_count; +} + +/** + * @brief Return the Host Channel state. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @retval Host channel state + * This parameter can be one of these values: + * HC_IDLE/ + * HC_XFRC/ + * HC_HALTED/ + * HC_NYET/ + * HC_NAK/ + * HC_STALL/ + * HC_XACTERR/ + * HC_BBLERR/ + * HC_DATATGLERR + */ +HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + return hhcd->hc[chnum].state; +} + +/** + * @brief Return the current Host frame number. + * @param hhcd HCD handle + * @retval Current Host frame number + */ +uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd) +{ + return (USB_GetCurrentFrame(hhcd->Instance)); +} + +/** + * @brief Return the Host enumeration speed. + * @param hhcd HCD handle + * @retval Enumeration speed + */ +uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd) +{ + return (USB_GetHostSpeed(hhcd->Instance)); +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup HCD_Private_Functions + * @{ + */ +/** + * @brief Handle Host Channel IN interrupt requests. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t USBx_BASE = (uint32_t)USBx; + uint32_t ch_num = (uint32_t)chnum; + + uint32_t tmpreg; + + if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); + hhcd->hc[ch_num].state = HC_XACTERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_BBERR) == USB_OTG_HCINT_BBERR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_BBERR); + hhcd->hc[ch_num].state = HC_BBLERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); + hhcd->hc[ch_num].state = HC_STALL; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); + hhcd->hc[ch_num].state = HC_DATATGLERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); + hhcd->hc[ch_num].state = HC_XACTERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else + { + /* ... */ + } + + if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) + { + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) + { + if (hhcd->Init.dma_enable != 0U) + { + hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].XferSize - \ + (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); + } + + hhcd->hc[ch_num].state = HC_XFRC; + hhcd->hc[ch_num].ErrCnt = 0U; + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); + + if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) || + (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK)) + { + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); + } + else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_INTR) || + (hhcd->hc[ch_num].ep_type == EP_TYPE_ISOC)) + { + USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; + hhcd->hc[ch_num].urb_state = URB_DONE; + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#else + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + else + { + /* ... */ + } + + if (hhcd->Init.dma_enable == 1U) + { + if (((hhcd->hc[ch_num].XferSize / hhcd->hc[ch_num].max_packet) & 1U) != 0U) + { + hhcd->hc[ch_num].toggle_in ^= 1U; + } + } + else + { + hhcd->hc[ch_num].toggle_in ^= 1U; + } + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) + { + if (hhcd->hc[ch_num].state == HC_XFRC) + { + hhcd->hc[ch_num].urb_state = URB_DONE; + } + else if (hhcd->hc[ch_num].state == HC_STALL) + { + hhcd->hc[ch_num].urb_state = URB_STALL; + } + else if ((hhcd->hc[ch_num].state == HC_XACTERR) || + (hhcd->hc[ch_num].state == HC_DATATGLERR)) + { + hhcd->hc[ch_num].ErrCnt++; + if (hhcd->hc[ch_num].ErrCnt > 2U) + { + hhcd->hc[ch_num].ErrCnt = 0U; + hhcd->hc[ch_num].urb_state = URB_ERROR; + } + else + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + + /* re-activate the channel */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + } + } + else if (hhcd->hc[ch_num].state == HC_NAK) + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + + /* re-activate the channel */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + } + else if (hhcd->hc[ch_num].state == HC_BBLERR) + { + hhcd->hc[ch_num].ErrCnt++; + hhcd->hc[ch_num].urb_state = URB_ERROR; + } + else + { + /* ... */ + } + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#else + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) + { + if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR) + { + hhcd->hc[ch_num].ErrCnt = 0U; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) || + (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK)) + { + hhcd->hc[ch_num].ErrCnt = 0U; + + if (hhcd->Init.dma_enable == 0U) + { + hhcd->hc[ch_num].state = HC_NAK; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + } + else + { + /* ... */ + } + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); + } + else + { + /* ... */ + } +} + +/** + * @brief Handle Host Channel OUT interrupt requests. + * @param hhcd HCD handle + * @param chnum Channel number. + * This parameter can be a value from 1 to 15 + * @retval none + */ +static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t USBx_BASE = (uint32_t)USBx; + uint32_t ch_num = (uint32_t)chnum; + uint32_t tmpreg; + uint32_t num_packets; + + if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR); + hhcd->hc[ch_num].state = HC_XACTERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK); + + if (hhcd->hc[ch_num].do_ping == 1U) + { + hhcd->hc[ch_num].do_ping = 0U; + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR); + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC) + { + hhcd->hc[ch_num].ErrCnt = 0U; + + /* transaction completed with NYET state, update do ping state */ + if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) + { + hhcd->hc[ch_num].do_ping = 1U; + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); + } + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC); + hhcd->hc[ch_num].state = HC_XFRC; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET) + { + hhcd->hc[ch_num].state = HC_NYET; + hhcd->hc[ch_num].do_ping = 1U; + hhcd->hc[ch_num].ErrCnt = 0U; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL) + { + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL); + hhcd->hc[ch_num].state = HC_STALL; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK) + { + hhcd->hc[ch_num].ErrCnt = 0U; + hhcd->hc[ch_num].state = HC_NAK; + + if (hhcd->hc[ch_num].do_ping == 0U) + { + if (hhcd->hc[ch_num].speed == HCD_DEVICE_SPEED_HIGH) + { + hhcd->hc[ch_num].do_ping = 1U; + } + } + + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR) + { + if (hhcd->Init.dma_enable == 0U) + { + hhcd->hc[ch_num].state = HC_XACTERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + } + else + { + hhcd->hc[ch_num].ErrCnt++; + if (hhcd->hc[ch_num].ErrCnt > 2U) + { + hhcd->hc[ch_num].ErrCnt = 0U; + hhcd->hc[ch_num].urb_state = URB_ERROR; + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#else + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + else + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + } + } + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR) + { + hhcd->hc[ch_num].state = HC_DATATGLERR; + (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num); + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR); + } + else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH) + { + if (hhcd->hc[ch_num].state == HC_XFRC) + { + hhcd->hc[ch_num].urb_state = URB_DONE; + if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) || + (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)) + { + if (hhcd->Init.dma_enable == 0U) + { + hhcd->hc[ch_num].toggle_out ^= 1U; + } + + if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[ch_num].xfer_len > 0U)) + { + num_packets = (hhcd->hc[ch_num].xfer_len + hhcd->hc[ch_num].max_packet - 1U) / hhcd->hc[ch_num].max_packet; + + if ((num_packets & 1U) != 0U) + { + hhcd->hc[ch_num].toggle_out ^= 1U; + } + } + } + } + else if (hhcd->hc[ch_num].state == HC_NAK) + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + } + else if (hhcd->hc[ch_num].state == HC_NYET) + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + } + else if (hhcd->hc[ch_num].state == HC_STALL) + { + hhcd->hc[ch_num].urb_state = URB_STALL; + } + else if ((hhcd->hc[ch_num].state == HC_XACTERR) || + (hhcd->hc[ch_num].state == HC_DATATGLERR)) + { + hhcd->hc[ch_num].ErrCnt++; + if (hhcd->hc[ch_num].ErrCnt > 2U) + { + hhcd->hc[ch_num].ErrCnt = 0U; + hhcd->hc[ch_num].urb_state = URB_ERROR; + } + else + { + hhcd->hc[ch_num].urb_state = URB_NOTREADY; + + /* re-activate the channel */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + } + } + else + { + /* ... */ + } + + __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH); + +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#else + HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + else + { + /* ... */ + } +} + +/** + * @brief Handle Rx Queue Level interrupt requests. + * @param hhcd HCD handle + * @retval none + */ +static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t USBx_BASE = (uint32_t)USBx; + uint32_t pktsts; + uint32_t pktcnt; + uint32_t GrxstspReg; + uint32_t xferSizePktCnt; + uint32_t tmpreg; + uint32_t ch_num; + + GrxstspReg = hhcd->Instance->GRXSTSP; + ch_num = GrxstspReg & USB_OTG_GRXSTSP_EPNUM; + pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17; + pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4; + + switch (pktsts) + { + case GRXSTS_PKTSTS_IN: + /* Read the data into the host buffer. */ + if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0)) + { + if ((hhcd->hc[ch_num].xfer_count + pktcnt) <= hhcd->hc[ch_num].xfer_len) + { + (void)USB_ReadPacket(hhcd->Instance, + hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt); + + /* manage multiple Xfer */ + hhcd->hc[ch_num].xfer_buff += pktcnt; + hhcd->hc[ch_num].xfer_count += pktcnt; + + /* get transfer size packet count */ + xferSizePktCnt = (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19; + + if ((hhcd->hc[ch_num].max_packet == pktcnt) && (xferSizePktCnt > 0U)) + { + /* re-activate the channel when more packets are expected */ + tmpreg = USBx_HC(ch_num)->HCCHAR; + tmpreg &= ~USB_OTG_HCCHAR_CHDIS; + tmpreg |= USB_OTG_HCCHAR_CHENA; + USBx_HC(ch_num)->HCCHAR = tmpreg; + hhcd->hc[ch_num].toggle_in ^= 1U; + } + } + else + { + hhcd->hc[ch_num].urb_state = URB_ERROR; + } + } + break; + + case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: + break; + + case GRXSTS_PKTSTS_IN_XFER_COMP: + case GRXSTS_PKTSTS_CH_HALTED: + default: + break; + } +} + +/** + * @brief Handle Host Port interrupt requests. + * @param hhcd HCD handle + * @retval None + */ +static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd) +{ + USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; + uint32_t USBx_BASE = (uint32_t)USBx; + __IO uint32_t hprt0; + __IO uint32_t hprt0_dup; + + /* Handle Host Port Interrupts */ + hprt0 = USBx_HPRT0; + hprt0_dup = USBx_HPRT0; + + hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \ + USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG); + + /* Check whether Port Connect detected */ + if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) + { + if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) + { +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->ConnectCallback(hhcd); +#else + HAL_HCD_Connect_Callback(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + hprt0_dup |= USB_OTG_HPRT_PCDET; + } + + /* Check whether Port Enable Changed */ + if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) + { + hprt0_dup |= USB_OTG_HPRT_PENCHNG; + + if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) + { + if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY) + { + if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) + { + (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ); + } + else + { + (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ); + } + } + else + { + if (hhcd->Init.speed == HCD_SPEED_FULL) + { + USBx_HOST->HFIR = 60000U; + } + } +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->PortEnabledCallback(hhcd); +#else + HAL_HCD_PortEnabled_Callback(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + + } + else + { +#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U) + hhcd->PortDisabledCallback(hhcd); +#else + HAL_HCD_PortDisabled_Callback(hhcd); +#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */ + } + } + + /* Check for an overcurrent */ + if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) + { + hprt0_dup |= USB_OTG_HPRT_POCCHNG; + } + + /* Clear Port Interrupts */ + USBx_HPRT0 = hprt0_dup; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */ +#endif /* HAL_HCD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c new file mode 100644 index 0000000..8034cf9 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c.c @@ -0,0 +1,7534 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c.c + * @author MCD Application Team + * @brief I2C HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Inter Integrated Circuit (I2C) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State, Mode and Error 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 I2C HAL driver can be used as follows: + + (#) Declare a I2C_HandleTypeDef handle structure, for example: + I2C_HandleTypeDef hi2c; + + (#)Initialize the I2C low level resources by implementing the HAL_I2C_MspInit() API: + (##) Enable the I2Cx interface clock + (##) I2C pins configuration + (+++) Enable the clock for the I2C GPIOs + (+++) Configure I2C pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the I2Cx interrupt priority + (+++) Enable the NVIC I2C IRQ Channel + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive stream + (+++) Enable the DMAx interface clock using + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx stream + (+++) Associate the initialized DMA handle to the hi2c DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on + the DMA Tx or Rx stream + + (#) Configure the Communication Speed, Duty cycle, Addressing mode, Own Address1, + Dual Addressing mode, Own Address2, General call and Nostretch mode in the hi2c Init structure. + + (#) Initialize the I2C registers by calling the HAL_I2C_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_I2C_MspInit() API. + + (#) To check if target device is ready for communication, use the function HAL_I2C_IsDeviceReady() + + (#) For I2C IO and IO MEM operations, three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Transmit in master mode an amount of data in blocking mode using HAL_I2C_Master_Transmit() + (+) Receive in master mode an amount of data in blocking mode using HAL_I2C_Master_Receive() + (+) Transmit in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Transmit() + (+) Receive in slave mode an amount of data in blocking mode using HAL_I2C_Slave_Receive() + + *** Polling mode IO MEM operation *** + ===================================== + [..] + (+) Write an amount of data in blocking mode to a specific memory address using HAL_I2C_Mem_Write() + (+) Read an amount of data in blocking mode from a specific memory address using HAL_I2C_Mem_Read() + + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode using HAL_I2C_Master_Receive_IT() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Transmit_IT() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode using HAL_I2C_Slave_Receive_IT() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + + *** Interrupt mode or DMA mode IO sequential operation *** + ========================================================== + [..] + (@) These interfaces allow to manage a sequential transfer with a repeated start condition + when a direction change during transfer + [..] + (+) A specific option field manage the different steps of a sequential transfer + (+) Option field values are defined through I2C_XferOptions_definition and are listed below: + (++) I2C_FIRST_AND_LAST_FRAME: No sequential usage, functional is same as associated interfaces in no sequential mode + (++) I2C_FIRST_FRAME: Sequential usage, this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition + (++) I2C_FIRST_AND_NEXT_FRAME: Sequential usage (Master only), this option allow to manage a sequence with start condition, address + and data to transfer without a final stop condition, an then permit a call the same master sequential interface + several times (like HAL_I2C_Master_Seq_Transmit_IT() then HAL_I2C_Master_Seq_Transmit_IT() + or HAL_I2C_Master_Seq_Transmit_DMA() then HAL_I2C_Master_Seq_Transmit_DMA()) + (++) I2C_NEXT_FRAME: Sequential usage, this option allow to manage a sequence with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and without a final stop condition in both cases + (++) I2C_LAST_FRAME: Sequential usage, this option allow to manage a sequance with a restart condition, address + and with new data to transfer if the direction change or manage only the new data to transfer + if no direction change and with a final stop condition in both cases + (++) I2C_LAST_FRAME_NO_STOP: Sequential usage (Master only), this option allow to manage a restart condition after several call of the same master sequential + interface several times (link with option I2C_FIRST_AND_NEXT_FRAME). + Usage can, transfer several bytes one by one using HAL_I2C_Master_Seq_Transmit_IT(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME) + or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME) + or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME) + or HAL_I2C_Master_Seq_Receive_DMA(option I2C_FIRST_AND_NEXT_FRAME then I2C_NEXT_FRAME). + Then usage of this option I2C_LAST_FRAME_NO_STOP at the last Transmit or Receive sequence permit to call the opposite interface Receive or Transmit + without stopping the communication and so generate a restart condition. + (++) I2C_OTHER_FRAME: Sequential usage (Master only), this option allow to manage a restart condition after each call of the same master sequential + interface. + Usage can, transfer several bytes one by one with a restart with slave address between each bytes using HAL_I2C_Master_Seq_Transmit_IT(option I2C_FIRST_FRAME then I2C_OTHER_FRAME) + or HAL_I2C_Master_Seq_Receive_IT(option I2C_FIRST_FRAME then I2C_OTHER_FRAME) + or HAL_I2C_Master_Seq_Transmit_DMA(option I2C_FIRST_FRAME then I2C_OTHER_FRAME) + or HAL_I2C_Master_Seq_Receive_DMA(option I2C_FIRST_FRAME then I2C_OTHER_FRAME). + Then usage of this option I2C_OTHER_AND_LAST_FRAME at the last frame to help automatic generation of STOP condition. + + (+) Different sequential I2C interfaces are listed below: + (++) Sequential transmit in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Seq_Transmit_IT() + or using HAL_I2C_Master_Seq_Transmit_DMA() + (+++) At transmission end of current frame transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (++) Sequential receive in master I2C mode an amount of data in non-blocking mode using HAL_I2C_Master_Seq_Receive_IT() + or using HAL_I2C_Master_Seq_Receive_DMA() + (+++) At reception end of current frame transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (++) Abort a master IT or DMA I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+++) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + (++) Enable/disable the Address listen mode in slave I2C mode using HAL_I2C_EnableListen_IT() HAL_I2C_DisableListen_IT() + (+++) When address slave I2C match, HAL_I2C_AddrCallback() is executed and user can + add his own code to check the Address Match Code and the transmission direction request by master (Write/Read). + (+++) At Listen mode end HAL_I2C_ListenCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_ListenCpltCallback() + (++) Sequential transmit in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Seq_Transmit_IT() + or using HAL_I2C_Slave_Seq_Transmit_DMA() + (+++) At transmission end of current frame transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (++) Sequential receive in slave I2C mode an amount of data in non-blocking mode using HAL_I2C_Slave_Seq_Receive_IT() + or using HAL_I2C_Slave_Seq_Receive_DMA() + (+++) At reception end of current frame transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (++) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + *** Interrupt mode IO MEM operation *** + ======================================= + [..] + (+) Write an amount of data in non-blocking mode with Interrupt to a specific memory address using + HAL_I2C_Mem_Write_IT() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with Interrupt from a specific memory address using + HAL_I2C_Mem_Read_IT() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + *** DMA mode IO operation *** + ============================== + [..] + (+) Transmit in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterTxCpltCallback() + (+) Receive in master mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Master_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MasterRxCpltCallback() + (+) Transmit in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Transmit_DMA() + (+) At transmission end of transfer, HAL_I2C_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveTxCpltCallback() + (+) Receive in slave mode an amount of data in non-blocking mode (DMA) using + HAL_I2C_Slave_Receive_DMA() + (+) At reception end of transfer, HAL_I2C_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_SlaveRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + (+) Abort a master I2C process communication with Interrupt using HAL_I2C_Master_Abort_IT() + (+) End of abort process, HAL_I2C_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_AbortCpltCallback() + + *** DMA mode IO MEM operation *** + ================================= + [..] + (+) Write an amount of data in non-blocking mode with DMA to a specific memory address using + HAL_I2C_Mem_Write_DMA() + (+) At Memory end of write transfer, HAL_I2C_MemTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemTxCpltCallback() + (+) Read an amount of data in non-blocking mode with DMA from a specific memory address using + HAL_I2C_Mem_Read_DMA() + (+) At Memory end of read transfer, HAL_I2C_MemRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_I2C_MemRxCpltCallback() + (+) In case of transfer Error, HAL_I2C_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2C_ErrorCallback() + + + *** I2C HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in I2C HAL driver. + + (+) __HAL_I2C_ENABLE: Enable the I2C peripheral + (+) __HAL_I2C_DISABLE: Disable the I2C peripheral + (+) __HAL_I2C_GET_FLAG: Checks whether the specified I2C flag is set or not + (+) __HAL_I2C_CLEAR_FLAG: Clear the specified I2C pending flag + (+) __HAL_I2C_ENABLE_IT: Enable the specified I2C interrupt + (+) __HAL_I2C_DISABLE_IT: Disable the specified I2C interrupt + + *** Callback registration *** + ============================================= + [..] + The compilation flag USE_HAL_I2C_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_I2C_RegisterCallback() or HAL_I2C_RegisterAddrCallback() + to register an interrupt callback. + [..] + Function HAL_I2C_RegisterCallback() allows to register following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) MemTxCpltCallback : callback for Memory transmission end of transfer. + (+) MemRxCpltCallback : callback for Memory reception end of transfer. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + For specific callback AddrCallback use dedicated register callbacks : HAL_I2C_RegisterAddrCallback(). + [..] + Use function HAL_I2C_UnRegisterCallback to reset a callback to the default + weak function. + HAL_I2C_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) MemTxCpltCallback : callback for Memory transmission end of transfer. + (+) MemRxCpltCallback : callback for Memory reception end of transfer. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + [..] + For callback AddrCallback use dedicated register callbacks : HAL_I2C_UnRegisterAddrCallback(). + [..] + By default, after the HAL_I2C_Init() and when the state is HAL_I2C_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_I2C_MasterTxCpltCallback(), HAL_I2C_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_I2C_Init()/ HAL_I2C_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_I2C_Init()/ HAL_I2C_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + [..] + Callbacks can be registered/unregistered in HAL_I2C_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_I2C_STATE_READY or HAL_I2C_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_I2C_RegisterCallback() before calling HAL_I2C_DeInit() + or HAL_I2C_Init() function. + [..] + When the compilation flag USE_HAL_I2C_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + + + [..] + (@) You can refer to the I2C HAL driver header file for more useful macros + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2C I2C + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup I2C_Private_Define + * @{ + */ +#define I2C_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ +#define I2C_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ +#define I2C_TIMEOUT_STOP_FLAG 5U /*!< Timeout 5 ms */ +#define I2C_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ + +/* Private define for @ref PreviousState usage */ +#define I2C_STATE_MSK ((uint32_t)((uint32_t)((uint32_t)HAL_I2C_STATE_BUSY_TX | (uint32_t)HAL_I2C_STATE_BUSY_RX) & (uint32_t)(~((uint32_t)HAL_I2C_STATE_READY)))) /*!< Mask State define, keep only RX and TX bits */ +#define I2C_STATE_NONE ((uint32_t)(HAL_I2C_MODE_NONE)) /*!< Default Value */ +#define I2C_STATE_MASTER_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_MASTER_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_TX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_TX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define I2C_STATE_SLAVE_BUSY_RX ((uint32_t)(((uint32_t)HAL_I2C_STATE_BUSY_RX & I2C_STATE_MSK) | (uint32_t)HAL_I2C_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/** @defgroup I2C_Private_Functions I2C Private Functions + * @{ + */ +/* Private functions to handle DMA transfer */ +static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma); +static void I2C_DMAError(DMA_HandleTypeDef *hdma); +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma); + +static void I2C_ITError(I2C_HandleTypeDef *hi2c); + +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart); + +/* Private functions to handle flags during polling transfer */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef I2C_WaitOnSTOPRequestThroughIT(I2C_HandleTypeDef *hi2c); +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c); + +/* Private functions for I2C transfer IRQ handler */ +static void I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c); +static void I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c); +static void I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c); +static void I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c); +static void I2C_Master_SB(I2C_HandleTypeDef *hi2c); +static void I2C_Master_ADD10(I2C_HandleTypeDef *hi2c); +static void I2C_Master_ADDR(I2C_HandleTypeDef *hi2c); + +static void I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c); +static void I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c); +static void I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c); +static void I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c); +static void I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c, uint32_t IT2Flags); +static void I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c); +static void I2C_Slave_AF(I2C_HandleTypeDef *hi2c); + +static void I2C_MemoryTransmit_TXE_BTF(I2C_HandleTypeDef *hi2c); + +/* Private function to Convert Specific options */ +static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c); + +/* Private function to flush DR register */ +static void I2C_Flush_DR(I2C_HandleTypeDef *hi2c); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup I2C_Exported_Functions I2C Exported Functions + * @{ + */ + +/** @defgroup I2C_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the I2Cx peripheral: + + (+) User must Implement HAL_I2C_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC). + + (+) Call the function HAL_I2C_Init() to configure the selected device with + the selected configuration: + (++) Communication Speed + (++) Duty cycle + (++) Addressing mode + (++) Own Address 1 + (++) Dual Addressing mode + (++) Own Address 2 + (++) General call mode + (++) Nostretch mode + + (+) Call the function HAL_I2C_DeInit() to restore the default configuration + of the selected I2Cx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the I2C according to the specified parameters + * in the I2C_InitTypeDef and initialize the associated handle. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c) +{ + uint32_t freqrange; + uint32_t pclk1; + + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_CLOCK_SPEED(hi2c->Init.ClockSpeed)); + assert_param(IS_I2C_DUTY_CYCLE(hi2c->Init.DutyCycle)); + assert_param(IS_I2C_OWN_ADDRESS1(hi2c->Init.OwnAddress1)); + assert_param(IS_I2C_ADDRESSING_MODE(hi2c->Init.AddressingMode)); + assert_param(IS_I2C_DUAL_ADDRESS(hi2c->Init.DualAddressMode)); + assert_param(IS_I2C_OWN_ADDRESS2(hi2c->Init.OwnAddress2)); + assert_param(IS_I2C_GENERAL_CALL(hi2c->Init.GeneralCallMode)); + assert_param(IS_I2C_NO_STRETCH(hi2c->Init.NoStretchMode)); + + if (hi2c->State == HAL_I2C_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2c->Lock = HAL_UNLOCKED; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + /* Init the I2C Callback settings */ + hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */ + hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */ + hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */ + hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */ + + if (hi2c->MspInitCallback == NULL) + { + hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + hi2c->MspInitCallback(hi2c); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_I2C_MspInit(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /*Reset I2C*/ + hi2c->Instance->CR1 |= I2C_CR1_SWRST; + hi2c->Instance->CR1 &= ~I2C_CR1_SWRST; + + /* Get PCLK1 frequency */ + pclk1 = HAL_RCC_GetPCLK1Freq(); + + /* Check the minimum allowed PCLK1 frequency */ + if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U) + { + return HAL_ERROR; + } + + /* Calculate frequency range */ + freqrange = I2C_FREQRANGE(pclk1); + + /*---------------------------- I2Cx CR2 Configuration ----------------------*/ + /* Configure I2Cx: Frequency range */ + MODIFY_REG(hi2c->Instance->CR2, I2C_CR2_FREQ, freqrange); + + /*---------------------------- I2Cx TRISE Configuration --------------------*/ + /* Configure I2Cx: Rise Time */ + MODIFY_REG(hi2c->Instance->TRISE, I2C_TRISE_TRISE, I2C_RISE_TIME(freqrange, hi2c->Init.ClockSpeed)); + + /*---------------------------- I2Cx CCR Configuration ----------------------*/ + /* Configure I2Cx: Speed */ + MODIFY_REG(hi2c->Instance->CCR, (I2C_CCR_FS | I2C_CCR_DUTY | I2C_CCR_CCR), I2C_SPEED(pclk1, hi2c->Init.ClockSpeed, hi2c->Init.DutyCycle)); + + /*---------------------------- I2Cx CR1 Configuration ----------------------*/ + /* Configure I2Cx: Generalcall and NoStretch mode */ + MODIFY_REG(hi2c->Instance->CR1, (I2C_CR1_ENGC | I2C_CR1_NOSTRETCH), (hi2c->Init.GeneralCallMode | hi2c->Init.NoStretchMode)); + + /*---------------------------- I2Cx OAR1 Configuration ---------------------*/ + /* Configure I2Cx: Own Address1 and addressing mode */ + MODIFY_REG(hi2c->Instance->OAR1, (I2C_OAR1_ADDMODE | I2C_OAR1_ADD8_9 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD0), (hi2c->Init.AddressingMode | hi2c->Init.OwnAddress1)); + + /*---------------------------- I2Cx OAR2 Configuration ---------------------*/ + /* Configure I2Cx: Dual mode and Own Address2 */ + MODIFY_REG(hi2c->Instance->OAR2, (I2C_OAR2_ENDUAL | I2C_OAR2_ADD2), (hi2c->Init.DualAddressMode | hi2c->Init.OwnAddress2)); + + /* Enable the selected I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + return HAL_OK; +} + +/** + * @brief DeInitialize the I2C peripheral. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c) +{ + /* Check the I2C handle allocation */ + if (hi2c == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the I2C Peripheral Clock */ + __HAL_I2C_DISABLE(hi2c); + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + if (hi2c->MspDeInitCallback == NULL) + { + hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + hi2c->MspDeInitCallback(hi2c); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_I2C_MspDeInit(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->State = HAL_I2C_STATE_RESET; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; +} + +/** + * @brief Initialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the I2C MSP. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User I2C Callback + * To be used instead of the weak predefined callback + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID + * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID + * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID + * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_RegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID, pI2C_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hi2c); + + if (HAL_I2C_STATE_READY == hi2c->State) + { + switch (CallbackID) + { + case HAL_I2C_MASTER_TX_COMPLETE_CB_ID : + hi2c->MasterTxCpltCallback = pCallback; + break; + + case HAL_I2C_MASTER_RX_COMPLETE_CB_ID : + hi2c->MasterRxCpltCallback = pCallback; + break; + + case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID : + hi2c->SlaveTxCpltCallback = pCallback; + break; + + case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID : + hi2c->SlaveRxCpltCallback = pCallback; + break; + + case HAL_I2C_LISTEN_COMPLETE_CB_ID : + hi2c->ListenCpltCallback = pCallback; + break; + + case HAL_I2C_MEM_TX_COMPLETE_CB_ID : + hi2c->MemTxCpltCallback = pCallback; + break; + + case HAL_I2C_MEM_RX_COMPLETE_CB_ID : + hi2c->MemRxCpltCallback = pCallback; + break; + + case HAL_I2C_ERROR_CB_ID : + hi2c->ErrorCallback = pCallback; + break; + + case HAL_I2C_ABORT_CB_ID : + hi2c->AbortCpltCallback = pCallback; + break; + + case HAL_I2C_MSPINIT_CB_ID : + hi2c->MspInitCallback = pCallback; + break; + + case HAL_I2C_MSPDEINIT_CB_ID : + hi2c->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_I2C_STATE_RESET == hi2c->State) + { + switch (CallbackID) + { + case HAL_I2C_MSPINIT_CB_ID : + hi2c->MspInitCallback = pCallback; + break; + + case HAL_I2C_MSPDEINIT_CB_ID : + hi2c->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + return status; +} + +/** + * @brief Unregister an I2C Callback + * I2C callback is redirected to the weak predefined callback + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * This parameter can be one of the following values: + * @arg @ref HAL_I2C_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_I2C_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_I2C_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_I2C_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_I2C_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_I2C_MEM_TX_COMPLETE_CB_ID Memory Tx Transfer callback ID + * @arg @ref HAL_I2C_MEM_RX_COMPLETE_CB_ID Memory Rx Transfer completed callback ID + * @arg @ref HAL_I2C_ERROR_CB_ID Error callback ID + * @arg @ref HAL_I2C_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_I2C_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_I2C_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_UnRegisterCallback(I2C_HandleTypeDef *hi2c, HAL_I2C_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hi2c); + + if (HAL_I2C_STATE_READY == hi2c->State) + { + switch (CallbackID) + { + case HAL_I2C_MASTER_TX_COMPLETE_CB_ID : + hi2c->MasterTxCpltCallback = HAL_I2C_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + break; + + case HAL_I2C_MASTER_RX_COMPLETE_CB_ID : + hi2c->MasterRxCpltCallback = HAL_I2C_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + break; + + case HAL_I2C_SLAVE_TX_COMPLETE_CB_ID : + hi2c->SlaveTxCpltCallback = HAL_I2C_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + break; + + case HAL_I2C_SLAVE_RX_COMPLETE_CB_ID : + hi2c->SlaveRxCpltCallback = HAL_I2C_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + break; + + case HAL_I2C_LISTEN_COMPLETE_CB_ID : + hi2c->ListenCpltCallback = HAL_I2C_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + break; + + case HAL_I2C_MEM_TX_COMPLETE_CB_ID : + hi2c->MemTxCpltCallback = HAL_I2C_MemTxCpltCallback; /* Legacy weak MemTxCpltCallback */ + break; + + case HAL_I2C_MEM_RX_COMPLETE_CB_ID : + hi2c->MemRxCpltCallback = HAL_I2C_MemRxCpltCallback; /* Legacy weak MemRxCpltCallback */ + break; + + case HAL_I2C_ERROR_CB_ID : + hi2c->ErrorCallback = HAL_I2C_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_I2C_ABORT_CB_ID : + hi2c->AbortCpltCallback = HAL_I2C_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_I2C_MSPINIT_CB_ID : + hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_I2C_MSPDEINIT_CB_ID : + hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_I2C_STATE_RESET == hi2c->State) + { + switch (CallbackID) + { + case HAL_I2C_MSPINIT_CB_ID : + hi2c->MspInitCallback = HAL_I2C_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_I2C_MSPDEINIT_CB_ID : + hi2c->MspDeInitCallback = HAL_I2C_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + return status; +} + +/** + * @brief Register the Slave Address Match I2C Callback + * To be used instead of the weak HAL_I2C_AddrCallback() predefined callback + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pCallback pointer to the Address Match Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_RegisterAddrCallback(I2C_HandleTypeDef *hi2c, pI2C_AddrCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hi2c); + + if (HAL_I2C_STATE_READY == hi2c->State) + { + hi2c->AddrCallback = pCallback; + } + else + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + return status; +} + +/** + * @brief UnRegister the Slave Address Match I2C Callback + * Info Ready I2C Callback is redirected to the weak HAL_I2C_AddrCallback() predefined callback + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_UnRegisterAddrCallback(I2C_HandleTypeDef *hi2c) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hi2c); + + if (HAL_I2C_STATE_READY == hi2c->State) + { + hi2c->AddrCallback = HAL_I2C_AddrCallback; /* Legacy weak AddrCallback */ + } + else + { + /* Update the error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2c); + return status; +} + +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + +/** + * @brief I2C data register flush process. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_Flush_DR(I2C_HandleTypeDef *hi2c) +{ + /* Write a dummy data in DR to clear TXE flag */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) != RESET) + { + hi2c->Instance->DR = 0x00U; + } +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the I2C data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2C IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2C_Master_Transmit() + (++) HAL_I2C_Master_Receive() + (++) HAL_I2C_Slave_Transmit() + (++) HAL_I2C_Slave_Receive() + (++) HAL_I2C_Mem_Write() + (++) HAL_I2C_Mem_Read() + (++) HAL_I2C_IsDeviceReady() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2C_Master_Transmit_IT() + (++) HAL_I2C_Master_Receive_IT() + (++) HAL_I2C_Slave_Transmit_IT() + (++) HAL_I2C_Slave_Receive_IT() + (++) HAL_I2C_Mem_Write_IT() + (++) HAL_I2C_Mem_Read_IT() + (++) HAL_I2C_Master_Seq_Transmit_IT() + (++) HAL_I2C_Master_Seq_Receive_IT() + (++) HAL_I2C_Slave_Seq_Transmit_IT() + (++) HAL_I2C_Slave_Seq_Receive_IT() + (++) HAL_I2C_EnableListen_IT() + (++) HAL_I2C_DisableListen_IT() + (++) HAL_I2C_Master_Abort_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2C_Master_Transmit_DMA() + (++) HAL_I2C_Master_Receive_DMA() + (++) HAL_I2C_Slave_Transmit_DMA() + (++) HAL_I2C_Slave_Receive_DMA() + (++) HAL_I2C_Mem_Write_DMA() + (++) HAL_I2C_Mem_Read_DMA() + (++) HAL_I2C_Master_Seq_Transmit_DMA() + (++) HAL_I2C_Master_Seq_Receive_DMA() + (++) HAL_I2C_Slave_Seq_Transmit_DMA() + (++) HAL_I2C_Slave_Seq_Receive_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_I2C_MasterTxCpltCallback() + (++) HAL_I2C_MasterRxCpltCallback() + (++) HAL_I2C_SlaveTxCpltCallback() + (++) HAL_I2C_SlaveRxCpltCallback() + (++) HAL_I2C_MemTxCpltCallback() + (++) HAL_I2C_MemRxCpltCallback() + (++) HAL_I2C_AddrCallback() + (++) HAL_I2C_ListenCpltCallback() + (++) HAL_I2C_ErrorCallback() + (++) HAL_I2C_AbortCpltCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while (hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + } + + /* Wait until BTF flag is set */ + if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address */ + if (I2C_MasterRequestRead(hi2c, DevAddress, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while (hi2c->XferSize > 0U) + { + if (hi2c->XferSize <= 3U) + { + /* One byte */ + if (hi2c->XferSize == 1U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if (hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + + if (hi2c->XferSize == 3U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmits in slave mode an amount of data in blocking mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* If 10bit addressing mode is selected */ + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT) + { + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while (hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + return HAL_ERROR; + } + + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + hi2c->XferSize--; + } + } + + /* Wait until AF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_AF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in blocking mode + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == (uint16_t)0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + while (hi2c->XferSize > 0U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + + /* Wait until STOP flag is set */ + if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + return HAL_ERROR; + } + + /* Clear STOP flag */ + __HAL_I2C_CLEAR_STOPFLAG(hi2c); + + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with Interrupt + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + HAL_StatusTypeDef dmaxferstatus; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + + if (hi2c->XferSize > 0U) + { + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in master mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + HAL_StatusTypeDef dmaxferstatus; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + + if (hi2c->XferSize > 0U) + { + if (hi2c->hdmarx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + + return HAL_OK; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive in slave mode an amount of data in non-blocking mode with DMA + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef dmaxferstatus; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + if (hi2c->hdmarx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + return HAL_OK; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Write an amount of data in blocking mode to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + while (hi2c->XferSize > 0U) + { + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + + /* Wait until BTF flag is set */ + if (I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in blocking mode from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + if (hi2c->XferSize == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferSize == 2U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + while (hi2c->XferSize > 0U) + { + if (hi2c->XferSize <= 3U) + { + /* One byte */ + if (hi2c->XferSize == 1U) + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* Two bytes */ + else if (hi2c->XferSize == 2U) + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + /* 3 Last bytes */ + else + { + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Wait until BTF flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + else + { + /* Wait until RXNE flag is set */ + if (I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferSize--; + hi2c->XferCount--; + } + } + } + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Write an amount of data in non-blocking mode with Interrupt to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Read an amount of data in non-blocking mode with Interrupt from a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + if (hi2c->XferSize > 0U) + { + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Write an amount of data in non-blocking mode with DMA to a specific memory address + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + __IO uint32_t count = 0U; + HAL_StatusTypeDef dmaxferstatus; + + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + if (hi2c->XferSize > 0U) + { + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferM1CpltCallback = NULL; + hi2c->hdmatx->XferM1HalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + /* Abort the ongoing DMA */ + dmaxferstatus = HAL_DMA_Abort_IT(hi2c->hdmatx); + + /* Prevent unused argument(s) compilation and MISRA warning */ + UNUSED(dmaxferstatus); + + /* Set the unused I2C DMA transfer complete callback to NULL */ + hi2c->hdmatx->XferCpltCallback = NULL; + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->XferSize = 0U; + hi2c->XferCount = 0U; + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); + + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + return HAL_OK; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_SIZE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads an amount of data in non-blocking mode with DMA from a specific memory address. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param pData Pointer to data buffer + * @param Size Amount of data to be read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size) +{ + /* Init tickstart for timeout management*/ + uint32_t tickstart = HAL_GetTick(); + __IO uint32_t count = 0U; + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MEM; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->Devaddress = DevAddress; + hi2c->Memaddress = MemAddress; + hi2c->MemaddSize = MemAddSize; + hi2c->EventCount = 0U; + + if (hi2c->XferSize > 0U) + { + if (hi2c->hdmarx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferM1CpltCallback = NULL; + hi2c->hdmarx->XferM1HalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + /* Abort the ongoing DMA */ + dmaxferstatus = HAL_DMA_Abort_IT(hi2c->hdmarx); + + /* Prevent unused argument(s) compilation and MISRA warning */ + UNUSED(dmaxferstatus); + + /* Set the unused I2C DMA transfer complete callback to NULL */ + hi2c->hdmarx->XferCpltCallback = NULL; + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->XferSize = 0U; + hi2c->XferCount = 0U; + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + return HAL_ERROR; + } + + if (hi2c->XferSize == 1U) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + else + { + /* Enable Last DMA bit */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Send Slave Address and Memory Address */ + if (I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, I2C_TIMEOUT_FLAG, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) +{ + /* Get tick */ + uint32_t tickstart = HAL_GetTick(); + uint32_t I2C_Trials = 0U; + FlagStatus tmp1; + FlagStatus tmp2; + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + do + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR or AF flag are set */ + /* Get tick */ + tickstart = HAL_GetTick(); + + tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); + tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); + while ((hi2c->State != HAL_I2C_STATE_TIMEOUT) && (tmp1 == RESET) && (tmp2 == RESET)) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + hi2c->State = HAL_I2C_STATE_TIMEOUT; + } + tmp1 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR); + tmp2 = __HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF); + } + + hi2c->State = HAL_I2C_STATE_READY; + + /* Check if the ADDR flag has been set */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_ADDR) == SET) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Clear ADDR Flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_OK; + } + else + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Wait until BUSY flag is reset */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_ERROR; + } + } + + /* Increment Trials */ + I2C_Trials++; + } + while (I2C_Trials < Trials); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with Interrupt. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t Prev_State = 0x00U; + __IO uint32_t count = 0x00U; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP) || (XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->Devaddress = DevAddress; + + Prev_State = hi2c->PreviousState; + + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_TX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in master I2C mode an amount of data in non-blocking mode with DMA. + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t Prev_State = 0x00U; + __IO uint32_t count = 0x00U; + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP) || (XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->Devaddress = DevAddress; + + Prev_State = hi2c->PreviousState; + + if (hi2c->XferSize > 0U) + { + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_TX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* If XferOptions is not associated to a new frame, mean no start bit is request, enable directly the DMA request */ + /* In other cases, DMA request is enabled after Slave address treatment in IRQHandler */ + if ((XferOptions == I2C_NEXT_FRAME) || (XferOptions == I2C_LAST_FRAME) || (XferOptions == I2C_LAST_FRAME_NO_STOP)) + { + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + } + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_TX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master I2C mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t Prev_State = 0x00U; + __IO uint32_t count = 0U; + uint32_t enableIT = (I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP) || (XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->Devaddress = DevAddress; + + Prev_State = hi2c->PreviousState; + + if ((hi2c->XferCount == 2U) && ((XferOptions == I2C_LAST_FRAME) || (XferOptions == I2C_LAST_FRAME_NO_STOP))) + { + if (Prev_State == I2C_STATE_MASTER_BUSY_RX) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Remove Enabling of IT_BUF, mean RXNE treatment, treat the 2 bytes through BTF */ + enableIT &= ~I2C_IT_BUF; + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_RX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable interrupts */ + __HAL_I2C_ENABLE_IT(hi2c, enableIT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in master mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t Prev_State = 0x00U; + __IO uint32_t count = 0U; + uint32_t enableIT = (I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP) || (XferOptions == I2C_FIRST_AND_LAST_FRAME) || (XferOptions == I2C_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = I2C_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_BUSY; + } + } + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Clear Last DMA bit */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + + hi2c->State = HAL_I2C_STATE_BUSY_RX; + hi2c->Mode = HAL_I2C_MODE_MASTER; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + hi2c->Devaddress = DevAddress; + + Prev_State = hi2c->PreviousState; + + if (hi2c->XferSize > 0U) + { + if ((hi2c->XferCount == 2U) && ((XferOptions == I2C_LAST_FRAME) || (XferOptions == I2C_LAST_FRAME_NO_STOP))) + { + if (Prev_State == I2C_STATE_MASTER_BUSY_RX) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + /* Enable Last DMA bit */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + if ((XferOptions == I2C_LAST_FRAME) || (XferOptions == I2C_OTHER_AND_LAST_FRAME) || (XferOptions == I2C_LAST_FRAME_NO_STOP)) + { + /* Enable Last DMA bit */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + } + } + if (hi2c->hdmarx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + if (dmaxferstatus == HAL_OK) + { + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_RX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Update interrupt for only EVT and ERR */ + enableIT = (I2C_IT_EVT | I2C_IT_ERR); + } + else + { + /* Update interrupt for only ERR */ + enableIT = I2C_IT_ERR; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* If XferOptions is not associated to a new frame, mean no start bit is request, enable directly the DMA request */ + /* In other cases, DMA request is enabled after Slave address treatment in IRQHandler */ + if ((XferOptions == I2C_NEXT_FRAME) || (XferOptions == I2C_LAST_FRAME) || (XferOptions == I2C_LAST_FRAME_NO_STOP)) + { + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + } + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, enableIT); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* If transfer direction not change and there is no request to start another frame, do not generate Restart Condition */ + /* Mean Previous state is same as current state */ + if ((Prev_State != I2C_STATE_MASTER_BUSY_RX) || (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(XferOptions) == 1)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable interrupts */ + __HAL_I2C_ENABLE_IT(hi2c, enableIT); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential transmit in slave mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Abort DMA Xfer if any */ + if (hi2c->hdmarx != NULL) + { + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + } + } + else if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Abort DMA Xfer if any */ + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + } + } + else + { + /* Nothing to do */ + } + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_TX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmatx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmatx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmatx->XferHalfCpltCallback = NULL; + hi2c->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmatx, (uint32_t)hi2c->pBuffPtr, (uint32_t)&hi2c->Instance->DR, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Enable DMA Request */ + hi2c->Instance->CR2 |= I2C_CR2_DMAEN; + + return HAL_OK; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in slave mode an amount of data in non-blocking mode with Interrupt + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Sequential receive in slave mode an amount of data in non-blocking mode with DMA + * @note This interface allow to manage repeated start condition when a direction change during transfer + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref I2C_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + HAL_StatusTypeDef dmaxferstatus; + + /* Check the parameters */ + assert_param(IS_I2C_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2c); + + /* Disable Interrupts, to prevent preemption during treatment in case of multicall */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* I2C cannot manage full duplex exchange so disable previous IT enabled if any */ + /* and then toggle the HAL slave RX state to TX state */ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Abort DMA Xfer if any */ + if (hi2c->hdmarx != NULL) + { + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + } + } + else if (hi2c->State == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Abort DMA Xfer if any */ + if (hi2c->hdmatx != NULL) + { + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + } + } + else + { + /* Nothing to do */ + } + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Disable Pos */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + + hi2c->State = HAL_I2C_STATE_BUSY_RX_LISTEN; + hi2c->Mode = HAL_I2C_MODE_SLAVE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Prepare transfer parameters */ + hi2c->pBuffPtr = pData; + hi2c->XferCount = Size; + hi2c->XferSize = hi2c->XferCount; + hi2c->XferOptions = XferOptions; + + if (hi2c->hdmarx != NULL) + { + /* Set the I2C DMA transfer complete callback */ + hi2c->hdmarx->XferCpltCallback = I2C_DMAXferCplt; + + /* Set the DMA error callback */ + hi2c->hdmarx->XferErrorCallback = I2C_DMAError; + + /* Set the unused DMA callbacks to NULL */ + hi2c->hdmarx->XferHalfCpltCallback = NULL; + hi2c->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + dmaxferstatus = HAL_DMA_Start_IT(hi2c->hdmarx, (uint32_t)&hi2c->Instance->DR, (uint32_t)hi2c->pBuffPtr, hi2c->XferSize); + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_LISTEN; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA_PARAM; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + if (dmaxferstatus == HAL_OK) + { + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Note : The I2C interrupts must be enabled after unlocking current process + to avoid the risk of I2C interrupt handle execution before current + process unlock */ + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + return HAL_OK; + } + else + { + /* Update I2C state */ + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Update I2C error code */ + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Check if the I2C is already enabled */ + if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + } + + /* Enable Address Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable EVT and ERR interrupt */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + tmp = (uint32_t)(hi2c->State) & I2C_STATE_MSK; + hi2c->PreviousState = tmp | (uint32_t)(hi2c->Mode); + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Disable Address Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master I2C IT or DMA process communication with Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(DevAddress); + + /* Abort Master transfer during Receive or Transmit process */ + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BUSY) != RESET) && (CurrentMode == HAL_I2C_MODE_MASTER)) + { + /* Process Locked */ + __HAL_LOCK(hi2c); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_ABORT; + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->XferCount = 0U; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c); + + return HAL_OK; + } + else + { + /* Wrong usage of abort function */ + /* This function should be used only in case of abort monitored by master device */ + /* Or periphal is not in busy state, mean there is no active sequence to be abort */ + return HAL_ERROR; + } +} + +/** + * @} + */ + +/** @defgroup I2C_IRQ_Handler_and_Callbacks IRQ Handler and Callbacks + * @{ + */ + +/** + * @brief This function handles I2C event interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + uint32_t sr1itflags; + uint32_t sr2itflags = 0U; + uint32_t itsources = READ_REG(hi2c->Instance->CR2); + uint32_t CurrentXferOptions = hi2c->XferOptions; + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + /* Master or Memory mode selected */ + if ((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) + { + sr2itflags = READ_REG(hi2c->Instance->SR2); + sr1itflags = READ_REG(hi2c->Instance->SR1); + + /* Exit IRQ event until Start Bit detected in case of Other frame requested */ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_SB) == RESET) && (IS_I2C_TRANSFER_OTHER_OPTIONS_REQUEST(CurrentXferOptions) == 1U)) + { + return; + } + + /* SB Set ----------------------------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_SB) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + /* Convert OTHER_xxx XferOptions if any */ + I2C_ConvertOtherXferOptions(hi2c); + + I2C_Master_SB(hi2c); + } + /* ADD10 Set -------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_ADD10) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_Master_ADD10(hi2c); + } + /* ADDR Set --------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_ADDR) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_Master_ADDR(hi2c); + } + /* I2C in mode Transmitter -----------------------------------------------*/ + else if (I2C_CHECK_FLAG(sr2itflags, I2C_FLAG_TRA) != RESET) + { + /* Do not check buffer and BTF flag if a Xfer DMA is on going */ + if (READ_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN) != I2C_CR2_DMAEN) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_TXE) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_BUF) != RESET) && (I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) == RESET)) + { + I2C_MasterTransmit_TXE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + if (CurrentState == HAL_I2C_STATE_BUSY_TX) + { + I2C_MasterTransmit_BTF(hi2c); + } + else /* HAL_I2C_MODE_MEM */ + { + if (CurrentMode == HAL_I2C_MODE_MEM) + { + I2C_MemoryTransmit_TXE_BTF(hi2c); + } + } + } + else + { + /* Do nothing */ + } + } + } + /* I2C in mode Receiver --------------------------------------------------*/ + else + { + /* Do not check buffer and BTF flag if a Xfer DMA is on going */ + if (READ_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN) != I2C_CR2_DMAEN) + { + /* RXNE set and BTF reset -----------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_RXNE) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_BUF) != RESET) && (I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) == RESET)) + { + I2C_MasterReceive_RXNE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_MasterReceive_BTF(hi2c); + } + else + { + /* Do nothing */ + } + } + } + } + /* Slave mode selected */ + else + { + /* If an error is detected, read only SR1 register to prevent */ + /* a clear of ADDR flags by reading SR2 after reading SR1 in Error treatment */ + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + sr1itflags = READ_REG(hi2c->Instance->SR1); + } + else + { + sr2itflags = READ_REG(hi2c->Instance->SR2); + sr1itflags = READ_REG(hi2c->Instance->SR1); + } + + /* ADDR set --------------------------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_ADDR) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + /* Now time to read SR2, this will clear ADDR flag automatically */ + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + sr2itflags = READ_REG(hi2c->Instance->SR2); + } + I2C_Slave_ADDR(hi2c, sr2itflags); + } + /* STOPF set --------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_STOPF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_Slave_STOPF(hi2c); + } + /* I2C in mode Transmitter -----------------------------------------------*/ + else if ((CurrentState == HAL_I2C_STATE_BUSY_TX) || (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_TXE) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_BUF) != RESET) && (I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) == RESET)) + { + I2C_SlaveTransmit_TXE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_SlaveTransmit_BTF(hi2c); + } + else + { + /* Do nothing */ + } + } + /* I2C in mode Receiver --------------------------------------------------*/ + else + { + /* RXNE set and BTF reset ----------------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_RXNE) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_BUF) != RESET) && (I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) == RESET)) + { + I2C_SlaveReceive_RXNE(hi2c); + } + /* BTF set -------------------------------------------------------------*/ + else if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BTF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_EVT) != RESET)) + { + I2C_SlaveReceive_BTF(hi2c); + } + else + { + /* Do nothing */ + } + } + } +} + +/** + * @brief This function handles I2C error interrupt request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +void HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c) +{ + HAL_I2C_ModeTypeDef tmp1; + uint32_t tmp2; + HAL_I2C_StateTypeDef tmp3; + uint32_t tmp4; + uint32_t sr1itflags = READ_REG(hi2c->Instance->SR1); + uint32_t itsources = READ_REG(hi2c->Instance->CR2); + uint32_t error = HAL_I2C_ERROR_NONE; + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + + /* I2C Bus error interrupt occurred ----------------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_BERR) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERR) != RESET)) + { + error |= HAL_I2C_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_BERR); + } + + /* I2C Arbitration Lost error interrupt occurred ---------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_ARLO) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERR) != RESET)) + { + error |= HAL_I2C_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_ARLO); + } + + /* I2C Acknowledge failure error interrupt occurred ------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_AF) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERR) != RESET)) + { + tmp1 = CurrentMode; + tmp2 = hi2c->XferCount; + tmp3 = hi2c->State; + tmp4 = hi2c->PreviousState; + if ((tmp1 == HAL_I2C_MODE_SLAVE) && (tmp2 == 0U) && \ + ((tmp3 == HAL_I2C_STATE_BUSY_TX) || (tmp3 == HAL_I2C_STATE_BUSY_TX_LISTEN) || \ + ((tmp3 == HAL_I2C_STATE_LISTEN) && (tmp4 == I2C_STATE_SLAVE_BUSY_TX)))) + { + I2C_Slave_AF(hi2c); + } + else + { + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + error |= HAL_I2C_ERROR_AF; + + /* Do not generate a STOP in case of Slave receive non acknowledge during transfer (mean not at the end of transfer) */ + if ((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + } + } + + /* I2C Over-Run/Under-Run interrupt occurred -------------------------------*/ + if ((I2C_CHECK_FLAG(sr1itflags, I2C_FLAG_OVR) != RESET) && (I2C_CHECK_IT_SOURCE(itsources, I2C_IT_ERR) != RESET)) + { + error |= HAL_I2C_ERROR_OVR; + /* Clear OVR flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_OVR); + } + + /* Call the Error Callback in case of Error detected -----------------------*/ + if (error != HAL_I2C_ERROR_NONE) + { + hi2c->ErrorCode |= error; + I2C_ITError(hi2c); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MasterRxCpltCallback could be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_SlaveRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref I2C_XferDirection_definition + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AddrCallback() could be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ListenCpltCallback() could be implemented in the user file + */ +} + +/** + * @brief Memory Tx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemTxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Memory Rx Transfer completed callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_MemRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief I2C error callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief I2C abort callback. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval None + */ +__weak void HAL_I2C_AbortCpltCallback(I2C_HandleTypeDef *hi2c) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2c); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2C_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2C_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State, Mode and Error functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permit to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the I2C handle state. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL state + */ +HAL_I2C_StateTypeDef HAL_I2C_GetState(I2C_HandleTypeDef *hi2c) +{ + /* Return I2C handle state */ + return hi2c->State; +} + +/** + * @brief Returns the I2C Master, Slave, Memory or no mode. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval HAL mode + */ +HAL_I2C_ModeTypeDef HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c) +{ + return hi2c->Mode; +} + +/** + * @brief Return the I2C error code. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval I2C Error Code + */ +uint32_t HAL_I2C_GetError(I2C_HandleTypeDef *hi2c) +{ + return hi2c->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2C_Private_Functions + * @{ + */ + +/** + * @brief Handle TXE flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_MasterTransmit_TXE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if ((hi2c->XferSize == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) + { + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterTxCpltCallback(hi2c); +#else + HAL_I2C_MasterTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemTxCpltCallback(hi2c); +#else + HAL_I2C_MemTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterTxCpltCallback(hi2c); +#else + HAL_I2C_MasterTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + } + else if ((CurrentState == HAL_I2C_STATE_BUSY_TX) || \ + ((CurrentMode == HAL_I2C_MODE_MEM) && (CurrentState == HAL_I2C_STATE_BUSY_RX))) + { + if (hi2c->XferCount == 0U) + { + /* Disable BUF interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + } + else + { + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + I2C_MemoryTransmit_TXE_BTF(hi2c); + } + else + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + } + } + else + { + /* Do nothing */ + } +} + +/** + * @brief Handle BTF flag for Master transmitter + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_MasterTransmit_BTF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + if (hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + else + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) && (CurrentXferOptions != I2C_NO_OPTION_FRAME)) + { + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_TX; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterTxCpltCallback(hi2c); +#else + HAL_I2C_MasterTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemTxCpltCallback(hi2c); +#else + HAL_I2C_MemTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterTxCpltCallback(hi2c); +#else + HAL_I2C_MasterTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + } + } + else + { + /* Do nothing */ + } +} + +/** + * @brief Handle TXE and BTF flag for Memory transmitter + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_MemoryTransmit_TXE_BTF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + if (hi2c->EventCount == 0U) + { + /* If Memory address size is 8Bit */ + if (hi2c->MemaddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); + + hi2c->EventCount += 2U; + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(hi2c->Memaddress); + + hi2c->EventCount++; + } + } + else if (hi2c->EventCount == 1U) + { + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(hi2c->Memaddress); + + hi2c->EventCount++; + } + else if (hi2c->EventCount == 2U) + { + if (CurrentState == HAL_I2C_STATE_BUSY_RX) + { + /* Generate Restart */ + hi2c->Instance->CR1 |= I2C_CR1_START; + + hi2c->EventCount++; + } + else if ((hi2c->XferCount > 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + else if ((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX)) + { + /* Generate Stop condition then Call TxCpltCallback() */ + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemTxCpltCallback(hi2c); +#else + HAL_I2C_MemTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + /* Do nothing */ + } + } + else + { + /* Clear TXE and BTF flag */ + I2C_Flush_DR(hi2c); + } +} + +/** + * @brief Handle RXNE flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_MasterReceive_RXNE(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + uint32_t tmp; + + tmp = hi2c->XferCount; + if (tmp > 3U) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + if (hi2c->XferCount == (uint16_t)3) + { + /* Disable BUF interrupt, this help to treat correctly the last 4 bytes + on BTF subroutine */ + /* Disable BUF interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + } + } + else if ((hi2c->XferOptions != I2C_FIRST_AND_NEXT_FRAME) && ((tmp == 1U) || (tmp == 0U))) + { + if (I2C_WaitOnSTOPRequestThroughIT(hi2c) == HAL_OK) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_NONE; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemRxCpltCallback(hi2c); +#else + HAL_I2C_MemRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterRxCpltCallback(hi2c); +#else + HAL_I2C_MasterRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + else + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call user error callback */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ErrorCallback(hi2c); +#else + HAL_I2C_ErrorCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + else + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + } + } +} + +/** + * @brief Handle BTF flag for Master receiver + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_MasterReceive_BTF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if (hi2c->XferCount == 4U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + else if (hi2c->XferCount == 3U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + if ((CurrentXferOptions != I2C_NEXT_FRAME) && (CurrentXferOptions != I2C_FIRST_AND_NEXT_FRAME)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + else if (hi2c->XferCount == 2U) + { + /* Prepare next transfer or stop current transfer */ + if ((CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME_NO_STOP)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + else if ((CurrentXferOptions == I2C_NEXT_FRAME) || (CurrentXferOptions == I2C_FIRST_AND_NEXT_FRAME)) + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + else if (CurrentXferOptions != I2C_LAST_FRAME_NO_STOP) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else + { + /* Do nothing */ + } + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + hi2c->State = HAL_I2C_STATE_READY; + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_NONE; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemRxCpltCallback(hi2c); +#else + HAL_I2C_MemRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX; +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterRxCpltCallback(hi2c); +#else + HAL_I2C_MasterRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + else + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } +} + +/** + * @brief Handle SB flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_Master_SB(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + if (hi2c->EventCount == 0U) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); + } + else + { + hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); + } + } + else + { + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave 7 Bits address */ + if (hi2c->State == HAL_I2C_STATE_BUSY_TX) + { + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(hi2c->Devaddress); + } + else + { + hi2c->Instance->DR = I2C_7BIT_ADD_READ(hi2c->Devaddress); + } + + if (((hi2c->hdmatx != NULL) && (hi2c->hdmatx->XferCpltCallback != NULL)) + || ((hi2c->hdmarx != NULL) && (hi2c->hdmarx->XferCpltCallback != NULL))) + { + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + } + } + else + { + if (hi2c->EventCount == 0U) + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(hi2c->Devaddress); + } + else if (hi2c->EventCount == 1U) + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(hi2c->Devaddress); + } + else + { + /* Do nothing */ + } + } + } +} + +/** + * @brief Handle ADD10 flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_Master_ADD10(I2C_HandleTypeDef *hi2c) +{ + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(hi2c->Devaddress); + + if (((hi2c->hdmatx != NULL) && (hi2c->hdmatx->XferCpltCallback != NULL)) + || ((hi2c->hdmarx != NULL) && (hi2c->hdmarx->XferCpltCallback != NULL))) + { + /* Enable DMA Request */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + } +} + +/** + * @brief Handle ADDR flag for Master + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_Master_ADDR(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + uint32_t CurrentXferOptions = hi2c->XferOptions; + uint32_t Prev_State = hi2c->PreviousState; + + if (hi2c->State == HAL_I2C_STATE_BUSY_RX) + { + if ((hi2c->EventCount == 0U) && (CurrentMode == HAL_I2C_MODE_MEM)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else if ((hi2c->EventCount == 0U) && (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_10BIT)) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + hi2c->EventCount++; + } + else + { + if (hi2c->XferCount == 0U) + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + else if (hi2c->XferCount == 1U) + { + if (CurrentXferOptions == I2C_NO_OPTION_FRAME) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + } + /* Prepare next transfer or stop current transfer */ + else if ((CurrentXferOptions != I2C_FIRST_AND_LAST_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME) \ + && ((Prev_State != I2C_STATE_MASTER_BUSY_RX) || (CurrentXferOptions == I2C_FIRST_FRAME))) + { + if ((CurrentXferOptions != I2C_NEXT_FRAME) && (CurrentXferOptions != I2C_FIRST_AND_NEXT_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME_NO_STOP)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + } + else if (hi2c->XferCount == 2U) + { + if ((CurrentXferOptions != I2C_NEXT_FRAME) && (CurrentXferOptions != I2C_FIRST_AND_NEXT_FRAME) && (CurrentXferOptions != I2C_LAST_FRAME_NO_STOP)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_POS); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + if (((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) && ((CurrentXferOptions == I2C_NO_OPTION_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME_NO_STOP) || (CurrentXferOptions == I2C_LAST_FRAME))) + { + /* Enable Last DMA bit */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + if (((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) && ((CurrentXferOptions == I2C_NO_OPTION_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME_NO_STOP) || (CurrentXferOptions == I2C_LAST_FRAME))) + { + /* Enable Last DMA bit */ + SET_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } + + /* Reset Event counter */ + hi2c->EventCount = 0U; + } + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + } +} + +/** + * @brief Handle TXE flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_SlaveTransmit_TXE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + if (hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + if ((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN)) + { + /* Last Byte is received, disable Interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveTxCpltCallback(hi2c); +#else + HAL_I2C_SlaveTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief Handle BTF flag for Slave transmitter + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_SlaveTransmit_BTF(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->XferCount != 0U) + { + /* Write data to DR */ + hi2c->Instance->DR = *hi2c->pBuffPtr; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } +} + +/** + * @brief Handle RXNE flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_SlaveReceive_RXNE(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + if (hi2c->XferCount != 0U) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + + if ((hi2c->XferCount == 0U) && (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + /* Last Byte is received, disable Interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_BUF); + + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveRxCpltCallback(hi2c); +#else + HAL_I2C_SlaveRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief Handle BTF flag for Slave receiver + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_SlaveReceive_BTF(I2C_HandleTypeDef *hi2c) +{ + if (hi2c->XferCount != 0U) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } +} + +/** + * @brief Handle ADD flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param IT2Flags Interrupt2 flags to handle. + * @retval None + */ +static void I2C_Slave_ADDR(I2C_HandleTypeDef *hi2c, uint32_t IT2Flags) +{ + uint8_t TransferDirection = I2C_DIRECTION_RECEIVE; + uint16_t SlaveAddrCode; + + if (((uint32_t)hi2c->State & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + /* Disable BUF interrupt, BUF enabling is manage through slave specific interface */ + __HAL_I2C_DISABLE_IT(hi2c, (I2C_IT_BUF)); + + /* Transfer Direction requested by Master */ + if (I2C_CHECK_FLAG(IT2Flags, I2C_FLAG_TRA) == RESET) + { + TransferDirection = I2C_DIRECTION_TRANSMIT; + } + + if (I2C_CHECK_FLAG(IT2Flags, I2C_FLAG_DUALF) == RESET) + { + SlaveAddrCode = (uint16_t)hi2c->Init.OwnAddress1; + } + else + { + SlaveAddrCode = (uint16_t)hi2c->Init.OwnAddress2; + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + /* Call Slave Addr callback */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->AddrCallback(hi2c, TransferDirection, SlaveAddrCode); +#else + HAL_I2C_AddrCallback(hi2c, TransferDirection, SlaveAddrCode); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + } +} + +/** + * @brief Handle STOPF flag for Slave + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_Slave_STOPF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear STOPF flag */ + __HAL_I2C_CLEAR_STOPFLAG(hi2c); + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* If a DMA is ongoing, Update handle size context */ + if ((hi2c->Instance->CR2 & I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + if ((CurrentState == HAL_I2C_STATE_BUSY_RX) || (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN)) + { + hi2c->XferCount = (uint16_t)(__HAL_DMA_GET_COUNTER(hi2c->hdmarx)); + + if (hi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Disable, stop the current DMA */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Abort DMA Xfer if any */ + if (HAL_DMA_GetState(hi2c->hdmarx) != HAL_DMA_STATE_READY) + { + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + } + else + { + hi2c->XferCount = (uint16_t)(__HAL_DMA_GET_COUNTER(hi2c->hdmatx)); + + if (hi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + + /* Disable, stop the current DMA */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + /* Abort DMA Xfer if any */ + if (HAL_DMA_GetState(hi2c->hdmatx) != HAL_DMA_STATE_READY) + { + /* Set the I2C DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + } + } + + /* All data are not transferred, so set error code accordingly */ + if (hi2c->XferCount != 0U) + { + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + + /* Update counter */ + hi2c->XferCount--; + } + + if (hi2c->XferCount != 0U) + { + /* Set ErrorCode corresponding to a Non-Acknowledge */ + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + } + } + + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + I2C_ITError(hi2c); + } + else + { + if (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveRxCpltCallback(hi2c); +#else + HAL_I2C_SlaveRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + + if (hi2c->State == HAL_I2C_STATE_LISTEN) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ListenCpltCallback(hi2c); +#else + HAL_I2C_ListenCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + if ((hi2c->PreviousState == I2C_STATE_SLAVE_BUSY_RX) || (CurrentState == HAL_I2C_STATE_BUSY_RX)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveRxCpltCallback(hi2c); +#else + HAL_I2C_SlaveRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + } +} + +/** + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @retval None + */ +static void I2C_Slave_AF(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + uint32_t CurrentXferOptions = hi2c->XferOptions; + + if (((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME)) && \ + (CurrentState == HAL_I2C_STATE_LISTEN)) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ListenCpltCallback(hi2c); +#else + HAL_I2C_ListenCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else if (CurrentState == HAL_I2C_STATE_BUSY_TX) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + + /* Clear AF flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /*Clear TXE flag*/ + I2C_Flush_DR(hi2c); + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveTxCpltCallback(hi2c); +#else + HAL_I2C_SlaveTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + /* Clear AF flag only */ + /* State Listen, but XferOptions == FIRST or NEXT */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + } +} + +/** + * @brief I2C interrupts error process + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ITError(I2C_HandleTypeDef *hi2c) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + uint32_t CurrentError; + + if (((CurrentMode == HAL_I2C_MODE_MASTER) || (CurrentMode == HAL_I2C_MODE_MEM)) && (CurrentState == HAL_I2C_STATE_BUSY_RX)) + { + /* Disable Pos bit in I2C CR1 when error occurred in Master/Mem Receive IT Process */ + hi2c->Instance->CR1 &= ~I2C_CR1_POS; + } + + if (((uint32_t)CurrentState & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + /* keep HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_LISTEN; + } + else + { + /* If state is an abort treatment on going, don't change state */ + /* This change will be do later */ + if ((READ_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN) != I2C_CR2_DMAEN) && (CurrentState != HAL_I2C_STATE_ABORT)) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + } + hi2c->PreviousState = I2C_STATE_NONE; + } + + /* Abort DMA transfer */ + if (READ_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN) == I2C_CR2_DMAEN) + { + hi2c->Instance->CR2 &= ~I2C_CR2_DMAEN; + + if (hi2c->hdmatx->State != HAL_DMA_STATE_READY) + { + /* Set the DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmatx->XferAbortCallback = I2C_DMAAbort; + + if (HAL_DMA_Abort_IT(hi2c->hdmatx) != HAL_OK) + { + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Call Directly XferAbortCallback function in case of error */ + hi2c->hdmatx->XferAbortCallback(hi2c->hdmatx); + } + } + else + { + /* Set the DMA Abort callback : + will lead to call HAL_I2C_ErrorCallback() at end of DMA abort procedure */ + hi2c->hdmarx->XferAbortCallback = I2C_DMAAbort; + + if (HAL_DMA_Abort_IT(hi2c->hdmarx) != HAL_OK) + { + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + } + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + /* Call Directly hi2c->hdmarx->XferAbortCallback function in case of error */ + hi2c->hdmarx->XferAbortCallback(hi2c->hdmarx); + } + } + } + else if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + } + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->AbortCpltCallback(hi2c); +#else + HAL_I2C_AbortCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + /* Store Last receive data if any */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == SET) + { + /* Read data from DR */ + *hi2c->pBuffPtr = (uint8_t)hi2c->Instance->DR; + + /* Increment Buffer pointer */ + hi2c->pBuffPtr++; + } + + /* Call user error callback */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ErrorCallback(hi2c); +#else + HAL_I2C_ErrorCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + + /* STOP Flag is not set after a NACK reception, BusError, ArbitrationLost, OverRun */ + CurrentError = hi2c->ErrorCode; + + if (((CurrentError & HAL_I2C_ERROR_BERR) == HAL_I2C_ERROR_BERR) || \ + ((CurrentError & HAL_I2C_ERROR_ARLO) == HAL_I2C_ERROR_ARLO) || \ + ((CurrentError & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF) || \ + ((CurrentError & HAL_I2C_ERROR_OVR) == HAL_I2C_ERROR_OVR)) + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR); + } + + /* So may inform upper layer that listen phase is stopped */ + /* during NACK error treatment */ + CurrentState = hi2c->State; + if (((hi2c->ErrorCode & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF) && (CurrentState == HAL_I2C_STATE_LISTEN)) + { + hi2c->XferOptions = I2C_NO_OPTION_FRAME; + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ListenCpltCallback(hi2c); +#else + HAL_I2C_ListenCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } +} + +/** + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_RX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_MasterRequestRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Timeout, uint32_t Tickstart) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start condition if first transfer */ + if ((CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_FIRST_FRAME) || (CurrentXferOptions == I2C_NO_OPTION_FRAME)) + { + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else if (hi2c->PreviousState == I2C_STATE_MASTER_BUSY_TX) + { + /* Generate ReStart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + } + else + { + /* Do nothing */ + } + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + if (hi2c->Init.AddressingMode == I2C_ADDRESSINGMODE_7BIT) + { + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + } + else + { + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_WRITE(DevAddress); + + /* Wait until ADD10 flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADD10, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_10BIT_ADDRESS(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Generate Restart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send header of slave address */ + hi2c->Instance->DR = I2C_10BIT_HEADER_READ(DevAddress); + } + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for write request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryWrite(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + + return HAL_OK; +} + +/** + * @brief Master sends target device address followed by internal memory address for read request. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param DevAddress Target device address: The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param MemAddress Internal memory address + * @param MemAddSize Size of internal memory address + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart) +{ + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + /* Clear ADDR flag */ + __HAL_I2C_CLEAR_ADDRFLAG(hi2c); + + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* If Memory address size is 8Bit */ + if (MemAddSize == I2C_MEMADD_SIZE_8BIT) + { + /* Send Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + /* If Memory address size is 16Bit */ + else + { + /* Send MSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress); + + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Send LSB of Memory Address */ + hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress); + } + + /* Wait until TXE flag is set */ + if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK) + { + if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + return HAL_ERROR; + } + + /* Generate Restart */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK) + { + if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START) + { + hi2c->ErrorCode = HAL_I2C_WRONG_START; + } + return HAL_TIMEOUT; + } + + /* Send slave address */ + hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress); + + /* Wait until ADDR flag is set */ + if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK) + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief DMA I2C process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAXferCplt(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + HAL_I2C_ModeTypeDef CurrentMode = hi2c->Mode; + uint32_t CurrentXferOptions = hi2c->XferOptions; + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Clear Complete callback */ + if (hi2c->hdmatx != NULL) + { + hi2c->hdmatx->XferCpltCallback = NULL; + } + if (hi2c->hdmarx != NULL) + { + hi2c->hdmarx->XferCpltCallback = NULL; + } + + if ((((uint32_t)CurrentState & (uint32_t)HAL_I2C_STATE_BUSY_TX) == (uint32_t)HAL_I2C_STATE_BUSY_TX) || ((((uint32_t)CurrentState & (uint32_t)HAL_I2C_STATE_BUSY_RX) == (uint32_t)HAL_I2C_STATE_BUSY_RX) && (CurrentMode == HAL_I2C_MODE_SLAVE))) + { + /* Disable DMA Request */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + hi2c->XferCount = 0U; + + if (CurrentState == HAL_I2C_STATE_BUSY_TX_LISTEN) + { + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_TX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveTxCpltCallback(hi2c); +#else + HAL_I2C_SlaveTxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else if (CurrentState == HAL_I2C_STATE_BUSY_RX_LISTEN) + { + /* Set state at HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_SLAVE_BUSY_RX; + hi2c->State = HAL_I2C_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->SlaveRxCpltCallback(hi2c); +#else + HAL_I2C_SlaveRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + /* Do nothing */ + } + + /* Enable EVT and ERR interrupt to treat end of transfer in IRQ handler */ + __HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + } + /* Check current Mode, in case of treatment DMA handler have been preempted by a prior interrupt */ + else if (hi2c->Mode != HAL_I2C_MODE_NONE) + { + if (hi2c->XferCount == (uint16_t)1) + { + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + } + + /* Disable EVT and ERR interrupt */ + __HAL_I2C_DISABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR); + + /* Prepare next transfer or stop current transfer */ + if ((CurrentXferOptions == I2C_NO_OPTION_FRAME) || (CurrentXferOptions == I2C_FIRST_AND_LAST_FRAME) || (CurrentXferOptions == I2C_OTHER_AND_LAST_FRAME) || (CurrentXferOptions == I2C_LAST_FRAME)) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + } + + /* Disable Last DMA */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_LAST); + + /* Disable DMA Request */ + CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN); + + hi2c->XferCount = 0U; + + /* Check if Errors has been detected during transfer */ + if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) + { +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ErrorCallback(hi2c); +#else + HAL_I2C_ErrorCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + + if (hi2c->Mode == HAL_I2C_MODE_MEM) + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_NONE; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MemRxCpltCallback(hi2c); +#else + HAL_I2C_MemRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->PreviousState = I2C_STATE_MASTER_BUSY_RX; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->MasterRxCpltCallback(hi2c); +#else + HAL_I2C_MasterRxCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + } + } + else + { + /* Do nothing */ + } +} + +/** + * @brief DMA I2C communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void I2C_DMAError(DMA_HandleTypeDef *hdma) +{ + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Clear Complete callback */ + if (hi2c->hdmatx != NULL) + { + hi2c->hdmatx->XferCpltCallback = NULL; + } + if (hi2c->hdmarx != NULL) + { + hi2c->hdmarx->XferCpltCallback = NULL; + } + + /* Ignore DMA FIFO error */ + if (HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) + { + /* Disable Acknowledge */ + hi2c->Instance->CR1 &= ~I2C_CR1_ACK; + + hi2c->XferCount = 0U; + + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + + hi2c->ErrorCode |= HAL_I2C_ERROR_DMA; + +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ErrorCallback(hi2c); +#else + HAL_I2C_ErrorCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } +} + +/** + * @brief DMA I2C communication abort callback + * (To be called at end of DMA Abort procedure). + * @param hdma DMA handle. + * @retval None + */ +static void I2C_DMAAbort(DMA_HandleTypeDef *hdma) +{ + __IO uint32_t count = 0U; + I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + HAL_I2C_StateTypeDef CurrentState = hi2c->State; + + /* During abort treatment, check that there is no pending STOP request */ + /* Wait until STOP flag is reset */ + count = I2C_TIMEOUT_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + if (count == 0U) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + break; + } + count--; + } + while (READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP); + + /* Clear Complete callback */ + if (hi2c->hdmatx != NULL) + { + hi2c->hdmatx->XferCpltCallback = NULL; + } + if (hi2c->hdmarx != NULL) + { + hi2c->hdmarx->XferCpltCallback = NULL; + } + + /* Disable Acknowledge */ + CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + hi2c->XferCount = 0U; + + /* Reset XferAbortCallback */ + if (hi2c->hdmatx != NULL) + { + hi2c->hdmatx->XferAbortCallback = NULL; + } + if (hi2c->hdmarx != NULL) + { + hi2c->hdmarx->XferAbortCallback = NULL; + } + + /* Disable I2C peripheral to prevent dummy data in buffer */ + __HAL_I2C_DISABLE(hi2c); + + /* Check if come from abort from user */ + if (hi2c->State == HAL_I2C_STATE_ABORT) + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode = HAL_I2C_ERROR_NONE; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->AbortCpltCallback(hi2c); +#else + HAL_I2C_AbortCpltCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } + else + { + if (((uint32_t)CurrentState & (uint32_t)HAL_I2C_STATE_LISTEN) == (uint32_t)HAL_I2C_STATE_LISTEN) + { + /* Renable I2C peripheral */ + __HAL_I2C_ENABLE(hi2c); + + /* Enable Acknowledge */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK); + + /* keep HAL_I2C_STATE_LISTEN */ + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_LISTEN; + } + else + { + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + } + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1) + hi2c->ErrorCallback(hi2c); +#else + HAL_I2C_ErrorCallback(hi2c); +#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */ + } +} + +/** + * @brief This function handles I2C Communication Timeout. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until flag is set */ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, Flag) == Status)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for Master addressing phase. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for I2C module + * @param Flag specifies the I2C flag to check. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnMasterAddressFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Flag, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET) + { + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Generate Stop */ + SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP); + + /* Clear AF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, Flag) == RESET)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of TXE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnTXEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of BTF flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnBTFFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of STOP flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnSTOPFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET) + { + /* Check if a NACK is detected */ + if (I2C_IsAcknowledgeFailed(hi2c) != HAL_OK) + { + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == RESET)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of STOP request through Interrupt. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnSTOPRequestThroughIT(I2C_HandleTypeDef *hi2c) +{ + __IO uint32_t count = 0U; + + /* Wait until STOP flag is reset */ + count = I2C_TIMEOUT_STOP_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + count--; + if (count == 0U) + { + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + return HAL_ERROR; + } + } + while (READ_BIT(hi2c->Instance->CR1, I2C_CR1_STOP) == I2C_CR1_STOP); + + return HAL_OK; +} + +/** + * @brief This function handles I2C Communication Timeout for specific usage of RXNE flag. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_WaitOnRXNEFlagUntilTimeout(I2C_HandleTypeDef *hi2c, uint32_t Timeout, uint32_t Tickstart) +{ + + while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET) + { + /* Check if a STOPF is detected */ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_STOPF) == SET) + { + /* Clear STOP Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + if ((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_RXNE) == RESET)) + { + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief This function handles Acknowledge failed detection during an I2C Communication. + * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2C. + * @retval HAL status + */ +static HAL_StatusTypeDef I2C_IsAcknowledgeFailed(I2C_HandleTypeDef *hi2c) +{ + if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_AF) == SET) + { + /* Clear NACKF Flag */ + __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_AF); + + hi2c->PreviousState = I2C_STATE_NONE; + hi2c->State = HAL_I2C_STATE_READY; + hi2c->Mode = HAL_I2C_MODE_NONE; + hi2c->ErrorCode |= HAL_I2C_ERROR_AF; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2c); + + return HAL_ERROR; + } + return HAL_OK; +} + +/** + * @brief Convert I2Cx OTHER_xxx XferOptions to functional XferOptions. + * @param hi2c I2C handle. + * @retval None + */ +static void I2C_ConvertOtherXferOptions(I2C_HandleTypeDef *hi2c) +{ + /* if user set XferOptions to I2C_OTHER_FRAME */ + /* it request implicitly to generate a restart condition */ + /* set XferOptions to I2C_FIRST_FRAME */ + if (hi2c->XferOptions == I2C_OTHER_FRAME) + { + hi2c->XferOptions = I2C_FIRST_FRAME; + } + /* else if user set XferOptions to I2C_OTHER_AND_LAST_FRAME */ + /* it request implicitly to generate a restart condition */ + /* then generate a stop condition at the end of transfer */ + /* set XferOptions to I2C_FIRST_AND_LAST_FRAME */ + else if (hi2c->XferOptions == I2C_OTHER_AND_LAST_FRAME) + { + hi2c->XferOptions = I2C_FIRST_AND_LAST_FRAME; + } + else + { + /* Nothing to do */ + } +} + +/** + * @} + */ + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c new file mode 100644 index 0000000..64aabaa --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2c_ex.c @@ -0,0 +1,182 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2c_ex.c + * @author MCD Application Team + * @brief I2C Extension HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of I2C extension peripheral: + * + Extension features 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 + ============================================================================== + ##### I2C peripheral extension features ##### + ============================================================================== + + [..] Comparing to other previous devices, the I2C interface for STM32F427xx/437xx/ + 429xx/439xx devices contains the following additional features : + + (+) Possibility to disable or enable Analog Noise Filter + (+) Use of a configured Digital Noise Filter + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to configure Noise Filter + (#) Configure I2C Analog noise filter using the function HAL_I2C_AnalogFilter_Config() + (#) Configure I2C Digital noise filter using the function HAL_I2C_DigitalFilter_Config() + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2CEx I2CEx + * @brief I2C HAL module driver + * @{ + */ + +#ifdef HAL_I2C_MODULE_ENABLED + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup I2CEx_Exported_Functions I2C Exported Functions + * @{ + */ + + +/** @defgroup I2CEx_Exported_Functions_Group1 Extension features functions + * @brief Extension features functions + * +@verbatim + =============================================================================== + ##### Extension features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure Noise Filters + +@endverbatim + * @{ + */ + +/** + * @brief Configures I2C Analog noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param AnalogFilter new state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigAnalogFilter(I2C_HandleTypeDef *hi2c, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_ANALOG_FILTER(AnalogFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Reset I2Cx ANOFF bit */ + hi2c->Instance->FLTR &= ~(I2C_FLTR_ANOFF); + + /* Disable the analog filter */ + hi2c->Instance->FLTR |= AnalogFilter; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures I2C Digital noise filter. + * @param hi2c pointer to a I2C_HandleTypeDef structure that contains + * the configuration information for the specified I2Cx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2CEx_ConfigDigitalFilter(I2C_HandleTypeDef *hi2c, uint32_t DigitalFilter) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance)); + assert_param(IS_I2C_DIGITAL_FILTER(DigitalFilter)); + + if (hi2c->State == HAL_I2C_STATE_READY) + { + hi2c->State = HAL_I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + __HAL_I2C_DISABLE(hi2c); + + /* Get the old register value */ + tmpreg = hi2c->Instance->FLTR; + + /* Reset I2Cx DNF bit [3:0] */ + tmpreg &= ~(I2C_FLTR_DNF); + + /* Set I2Cx DNF coefficient */ + tmpreg |= DigitalFilter; + + /* Store the new register value */ + hi2c->Instance->FLTR = tmpreg; + + __HAL_I2C_ENABLE(hi2c); + + hi2c->State = HAL_I2C_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @} + */ + +/** + * @} + */ +#endif + +#endif /* HAL_I2C_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c new file mode 100644 index 0000000..700a0ca --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s.c @@ -0,0 +1,2094 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2s.c + * @author MCD Application Team + * @brief I2S HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Integrated Interchip Sound (I2S) peripheral: + * + Initialization and de-initialization functions + * + IO operation 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 I2S HAL driver can be used as follow: + + (#) Declare a I2S_HandleTypeDef handle structure. + (#) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API: + (##) Enable the SPIx interface clock. + (##) I2S pins configuration: + (+++) Enable the clock for the I2S GPIOs. + (+++) Configure these I2S pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT() + and HAL_I2S_Receive_IT() APIs). + (+++) Configure the I2Sx interrupt priority. + (+++) Enable the NVIC I2S IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA() + and HAL_I2S_Receive_DMA() APIs: + (+++) Declare a DMA handle structure for the Tx/Rx Stream/Channel. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx Stream/Channel. + (+++) Associate the initialized DMA handle to the I2S DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the + DMA Tx/Rx Stream/Channel. + + (#) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity + using HAL_I2S_Init() function. + + -@- The specific I2S interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_I2S_ENABLE_IT() and __HAL_I2S_DISABLE_IT() inside the transmit and receive process. + -@- Make sure that either: + (+@) I2S PLL clock is configured or + (+@) External clock source is configured after setting correctly + the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file. + + (#) Three mode of operations are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_I2S_Transmit() + (+) Receive an amount of data in blocking mode using HAL_I2S_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_I2S_Transmit_IT() + (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback + (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_I2S_Receive_IT() + (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback + (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_RxCpltCallback + (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2S_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_I2S_Transmit_DMA() + (+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback + (+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_I2S_Receive_DMA() + (+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback + (+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_RxCpltCallback + (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2S_ErrorCallback + (+) Pause the DMA Transfer using HAL_I2S_DMAPause() + (+) Resume the DMA Transfer using HAL_I2S_DMAResume() + (+) Stop the DMA Transfer using HAL_I2S_DMAStop() + In Slave mode, if HAL_I2S_DMAStop is used to stop the communication, an error + HAL_I2S_ERROR_BUSY_LINE_RX is raised as the master continue to transmit data. + In this case __HAL_I2S_FLUSH_RX_DR macro must be used to flush the remaining data + inside DR register and avoid using DeInit/Init process for the next transfer. + + *** I2S HAL driver macros list *** + =================================== + [..] + Below the list of most used macros in I2S HAL driver. + + (+) __HAL_I2S_ENABLE: Enable the specified SPI peripheral (in I2S mode) + (+) __HAL_I2S_DISABLE: Disable the specified SPI peripheral (in I2S mode) + (+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts + (+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts + (+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not + (+) __HAL_I2S_FLUSH_RX_DR: Read DR Register to Flush RX Data + + [..] + (@) You can refer to the I2S HAL driver header file for more useful macros + + *** I2S HAL driver macros list *** + =================================== + [..] + Callback registration: + + (#) The compilation flag USE_HAL_I2S_REGISTER_CALLBACKS when set to 1U + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_I2S_RegisterCallback() to register an interrupt callback. + + Function HAL_I2S_RegisterCallback() allows to register following callbacks: + (++) TxCpltCallback : I2S Tx Completed callback + (++) RxCpltCallback : I2S Rx Completed callback + (++) TxRxCpltCallback : I2S TxRx Completed callback + (++) TxHalfCpltCallback : I2S Tx Half Completed callback + (++) RxHalfCpltCallback : I2S Rx Half Completed callback + (++) ErrorCallback : I2S Error callback + (++) MspInitCallback : I2S Msp Init callback + (++) MspDeInitCallback : I2S Msp DeInit callback + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + + (#) Use function HAL_I2S_UnRegisterCallback to reset a callback to the default + weak function. + HAL_I2S_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (++) TxCpltCallback : I2S Tx Completed callback + (++) RxCpltCallback : I2S Rx Completed callback + (++) TxRxCpltCallback : I2S TxRx Completed callback + (++) TxHalfCpltCallback : I2S Tx Half Completed callback + (++) RxHalfCpltCallback : I2S Rx Half Completed callback + (++) ErrorCallback : I2S Error callback + (++) MspInitCallback : I2S Msp Init callback + (++) MspDeInitCallback : I2S Msp DeInit callback + + [..] + By default, after the HAL_I2S_Init() and when the state is HAL_I2S_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_I2S_MasterTxCpltCallback(), HAL_I2S_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_I2S_Init()/ HAL_I2S_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_I2S_Init()/ HAL_I2S_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + + [..] + Callbacks can be registered/unregistered in HAL_I2S_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_I2S_STATE_READY or HAL_I2S_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_I2S_RegisterCallback() before calling HAL_I2S_DeInit() + or HAL_I2S_Init() function. + + [..] + When the compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#ifdef HAL_I2S_MODULE_ENABLED + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup I2S I2S + * @brief I2S HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define I2S_TIMEOUT_FLAG 100U /*!< Timeout 100 ms */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup I2S_Private_Functions I2S Private Functions + * @{ + */ +static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma); +static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma); +static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void I2S_DMAError(DMA_HandleTypeDef *hdma); +static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s); +static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s); +static void I2S_IRQHandler(I2S_HandleTypeDef *hi2s); +static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State, + uint32_t Timeout); +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup I2S_Exported_Functions I2S Exported Functions + * @{ + */ + +/** @defgroup I2S_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + de-initialize the I2Sx peripheral in simplex mode: + + (+) User must Implement HAL_I2S_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_I2S_Init() to configure the selected device with + the selected configuration: + (++) Mode + (++) Standard + (++) Data Format + (++) MCLK Output + (++) Audio frequency + (++) Polarity + (++) Full duplex mode + + (+) Call the function HAL_I2S_DeInit() to restore the default configuration + of the selected I2Sx peripheral. + @endverbatim + * @{ + */ + +/** + * @brief Initializes the I2S according to the specified parameters + * in the I2S_InitTypeDef and create the associated handle. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s) +{ + uint32_t i2sdiv; + uint32_t i2sodd; + uint32_t packetlength; + uint32_t tmp; + uint32_t i2sclk; +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + uint16_t tmpreg; +#endif + + /* Check the I2S handle allocation */ + if (hi2s == NULL) + { + return HAL_ERROR; + } + + /* Check the I2S parameters */ + assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance)); + assert_param(IS_I2S_MODE(hi2s->Init.Mode)); + assert_param(IS_I2S_STANDARD(hi2s->Init.Standard)); + assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat)); + assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput)); + assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq)); + assert_param(IS_I2S_CPOL(hi2s->Init.CPOL)); + assert_param(IS_I2S_CLOCKSOURCE(hi2s->Init.ClockSource)); + + if (hi2s->State == HAL_I2S_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hi2s->Lock = HAL_UNLOCKED; + + /* Initialize Default I2S IrqHandler ISR */ + hi2s->IrqHandlerISR = I2S_IRQHandler; + +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + /* Init the I2S Callback settings */ + hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */ +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + hi2s->TxRxCpltCallback = HAL_I2SEx_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + hi2s->TxRxHalfCpltCallback = HAL_I2SEx_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hi2s->MspInitCallback == NULL) + { + hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + hi2s->MspInitCallback(hi2s); +#else + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_I2S_MspInit(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + + hi2s->State = HAL_I2S_STATE_BUSY; + + /*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/ + /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ + CLEAR_BIT(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \ + SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \ + SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD)); + hi2s->Instance->I2SPR = 0x0002U; + + /*----------------------- I2SPR: I2SDIV and ODD Calculation -----------------*/ + /* If the requested audio frequency is not the default, compute the prescaler */ + if (hi2s->Init.AudioFreq != I2S_AUDIOFREQ_DEFAULT) + { + /* Check the frame length (For the Prescaler computing) ********************/ + if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B) + { + /* Packet length is 16 bits */ + packetlength = 16U; + } + else + { + /* Packet length is 32 bits */ + packetlength = 32U; + } + + /* I2S standard */ + if (hi2s->Init.Standard <= I2S_STANDARD_LSB) + { + /* In I2S standard packet length is multiplied by 2 */ + packetlength = packetlength * 2U; + } + + /* Get the source clock value **********************************************/ +#if defined(I2S_APB1_APB2_FEATURE) + if (IS_I2S_APB1_INSTANCE(hi2s->Instance)) + { + i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S_APB1); + } + else + { + i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S_APB2); + } +#else + i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S); +#endif /* I2S_APB1_APB2_FEATURE */ + + /* Compute the Real divider depending on the MCLK output state, with a floating point */ + if (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE) + { + /* MCLK output is enabled */ + if (hi2s->Init.DataFormat != I2S_DATAFORMAT_16B) + { + tmp = (uint32_t)(((((i2sclk / (packetlength * 4U)) * 10U) / hi2s->Init.AudioFreq)) + 5U); + } + else + { + tmp = (uint32_t)(((((i2sclk / (packetlength * 8U)) * 10U) / hi2s->Init.AudioFreq)) + 5U); + } + } + else + { + /* MCLK output is disabled */ + tmp = (uint32_t)(((((i2sclk / packetlength) * 10U) / hi2s->Init.AudioFreq)) + 5U); + } + + /* Remove the flatting point */ + tmp = tmp / 10U; + + /* Check the parity of the divider */ + i2sodd = (uint32_t)(tmp & (uint32_t)1U); + + /* Compute the i2sdiv prescaler */ + i2sdiv = (uint32_t)((tmp - i2sodd) / 2U); + + /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ + i2sodd = (uint32_t)(i2sodd << 8U); + } + else + { + /* Set the default values */ + i2sdiv = 2U; + i2sodd = 0U; + } + + /* Test if the divider is 1 or 0 or greater than 0xFF */ + if ((i2sdiv < 2U) || (i2sdiv > 0xFFU)) + { + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_PRESCALER); + return HAL_ERROR; + } + + /*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/ + + /* Write to SPIx I2SPR register the computed value */ + hi2s->Instance->I2SPR = (uint32_t)((uint32_t)i2sdiv | (uint32_t)(i2sodd | (uint32_t)hi2s->Init.MCLKOutput)); + + /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ + /* And configure the I2S with the I2S_InitStruct values */ + MODIFY_REG(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \ + SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \ + SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \ + SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD), \ + (SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode | \ + hi2s->Init.Standard | hi2s->Init.DataFormat | \ + hi2s->Init.CPOL)); + +#if defined(SPI_I2SCFGR_ASTRTEN) + if ((hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) || ((hi2s->Init.Standard == I2S_STANDARD_PCM_LONG))) + { + /* Write to SPIx I2SCFGR */ + SET_BIT(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_ASTRTEN); + } +#endif /* SPI_I2SCFGR_ASTRTEN */ + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + + /* Configure the I2S extended if the full duplex mode is enabled */ + assert_param(IS_I2S_FULLDUPLEX_MODE(hi2s->Init.FullDuplexMode)); + + if (hi2s->Init.FullDuplexMode == I2S_FULLDUPLEXMODE_ENABLE) + { + /* Set FullDuplex I2S IrqHandler ISR if FULLDUPLEXMODE is enabled */ + hi2s->IrqHandlerISR = HAL_I2SEx_FullDuplex_IRQHandler; + + /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */ + CLEAR_BIT(I2SxEXT(hi2s->Instance)->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \ + SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \ + SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD)); + I2SxEXT(hi2s->Instance)->I2SPR = 2U; + + /* Get the I2SCFGR register value */ + tmpreg = I2SxEXT(hi2s->Instance)->I2SCFGR; + + /* Get the mode to be configured for the extended I2S */ + if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)) + { + tmp = I2S_MODE_SLAVE_RX; + } + else /* I2S_MODE_MASTER_RX || I2S_MODE_SLAVE_RX */ + { + tmp = I2S_MODE_SLAVE_TX; + } + + /* Configure the I2S Slave with the I2S Master parameter values */ + tmpreg |= (uint16_t)((uint16_t)SPI_I2SCFGR_I2SMOD | \ + (uint16_t)tmp | \ + (uint16_t)hi2s->Init.Standard | \ + (uint16_t)hi2s->Init.DataFormat | \ + (uint16_t)hi2s->Init.CPOL); + + /* Write to SPIx I2SCFGR */ + WRITE_REG(I2SxEXT(hi2s->Instance)->I2SCFGR, tmpreg); + } +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->State = HAL_I2S_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the I2S peripheral + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s) +{ + /* Check the I2S handle allocation */ + if (hi2s == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance)); + + hi2s->State = HAL_I2S_STATE_BUSY; + + /* Disable the I2S Peripheral Clock */ + __HAL_I2S_DISABLE(hi2s); + +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + if (hi2s->MspDeInitCallback == NULL) + { + hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + hi2s->MspDeInitCallback(hi2s); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + HAL_I2S_MspDeInit(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->State = HAL_I2S_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hi2s); + + return HAL_OK; +} + +/** + * @brief I2S MSP Init + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_MspInit could be implemented in the user file + */ +} + +/** + * @brief I2S MSP DeInit + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User I2S Callback + * To be used instead of the weak predefined callback + * @param hi2s Pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for the specified I2S. + * @param CallbackID ID of the callback to be registered + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID, + pI2S_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hi2s->ErrorCode |= HAL_I2S_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hi2s); + + if (HAL_I2S_STATE_READY == hi2s->State) + { + switch (CallbackID) + { + case HAL_I2S_TX_COMPLETE_CB_ID : + hi2s->TxCpltCallback = pCallback; + break; + + case HAL_I2S_RX_COMPLETE_CB_ID : + hi2s->RxCpltCallback = pCallback; + break; + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + case HAL_I2S_TX_RX_COMPLETE_CB_ID : + hi2s->TxRxCpltCallback = pCallback; + break; +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + case HAL_I2S_TX_HALF_COMPLETE_CB_ID : + hi2s->TxHalfCpltCallback = pCallback; + break; + + case HAL_I2S_RX_HALF_COMPLETE_CB_ID : + hi2s->RxHalfCpltCallback = pCallback; + break; + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + case HAL_I2S_TX_RX_HALF_COMPLETE_CB_ID : + hi2s->TxRxHalfCpltCallback = pCallback; + break; +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + case HAL_I2S_ERROR_CB_ID : + hi2s->ErrorCallback = pCallback; + break; + + case HAL_I2S_MSPINIT_CB_ID : + hi2s->MspInitCallback = pCallback; + break; + + case HAL_I2S_MSPDEINIT_CB_ID : + hi2s->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_I2S_STATE_RESET == hi2s->State) + { + switch (CallbackID) + { + case HAL_I2S_MSPINIT_CB_ID : + hi2s->MspInitCallback = pCallback; + break; + + case HAL_I2S_MSPDEINIT_CB_ID : + hi2s->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2s); + return status; +} + +/** + * @brief Unregister an I2S Callback + * I2S callback is redirected to the weak predefined callback + * @param hi2s Pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for the specified I2S. + * @param CallbackID ID of the callback to be unregistered + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_UnRegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hi2s); + + if (HAL_I2S_STATE_READY == hi2s->State) + { + switch (CallbackID) + { + case HAL_I2S_TX_COMPLETE_CB_ID : + hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_I2S_RX_COMPLETE_CB_ID : + hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + case HAL_I2S_TX_RX_COMPLETE_CB_ID : + hi2s->TxRxCpltCallback = HAL_I2SEx_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + break; +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + case HAL_I2S_TX_HALF_COMPLETE_CB_ID : + hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_I2S_RX_HALF_COMPLETE_CB_ID : + hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + case HAL_I2S_TX_RX_HALF_COMPLETE_CB_ID : + hi2s->TxRxHalfCpltCallback = HAL_I2SEx_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ + break; +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + case HAL_I2S_ERROR_CB_ID : + hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_I2S_MSPINIT_CB_ID : + hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_I2S_MSPDEINIT_CB_ID : + hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_I2S_STATE_RESET == hi2s->State) + { + switch (CallbackID) + { + case HAL_I2S_MSPINIT_CB_ID : + hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_I2S_MSPDEINIT_CB_ID : + hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hi2s); + return status; +} +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup I2S_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the I2S data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2S_Transmit() + (++) HAL_I2S_Receive() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2S_Transmit_IT() + (++) HAL_I2S_Receive_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2S_Transmit_DMA() + (++) HAL_I2S_Receive_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_I2S_TxCpltCallback() + (++) HAL_I2S_RxCpltCallback() + (++) HAL_I2S_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmit an amount of data in blocking mode + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @param Timeout Timeout duration + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_TX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pTxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + } + + tmpreg_cfgr = hi2s->Instance->I2SCFGR; + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + /* Wait until TXE flag is set */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + + while (hi2s->TxXferCount > 0U) + { + hi2s->Instance->DR = (*hi2s->pTxBuffPtr); + hi2s->pTxBuffPtr++; + hi2s->TxXferCount--; + + /* Wait until TXE flag is set */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + + /* Check if an underrun occurs */ + if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET) + { + /* Clear underrun flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + } + } + + /* Check if Slave mode is selected */ + if (((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX) + || ((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX)) + { + /* Wait until Busy flag is reset */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + } + + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Receive an amount of data in blocking mode + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @param Timeout Timeout duration + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate + * in continuous way and as the I2S is not disabled at the end of the I2S transaction. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_RX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pRxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + /* Check if Master Receiver mode is selected */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) + { + /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read + access to the SPI_SR register. */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + } + + /* Receive data */ + while (hi2s->RxXferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + + (*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR; + hi2s->pRxBuffPtr++; + hi2s->RxXferCount--; + + /* Check if an overrun occurs */ + if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET) + { + /* Clear overrun flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + } + } + + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with Interrupt + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_TX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pTxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + } + + /* Enable TXE and ERR interrupt */ + __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Receive an amount of data in non-blocking mode with Interrupt + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to the Receive data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @note It is recommended to use DMA for the I2S receiver to avoid de-synchronization + * between Master and Slave otherwise the I2S interrupt should be optimized. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_RX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pRxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + /* Enable RXNE and ERR interrupt */ + __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with DMA + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to the Transmit data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_TX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pTxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + } + + /* Set the I2S Tx DMA Half transfer complete callback */ + hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt; + + /* Set the I2S Tx DMA transfer complete callback */ + hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt; + + /* Set the DMA error callback */ + hi2s->hdmatx->XferErrorCallback = I2S_DMAError; + + /* Enable the Tx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx, + (uint32_t)hi2s->pTxBuffPtr, + (uint32_t)&hi2s->Instance->DR, + hi2s->TxXferSize)) + { + /* Update SPI error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + hi2s->State = HAL_I2S_STATE_READY; + + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + + /* Check if the I2S is already enabled */ + if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + /* Check if the I2S Tx request is already enabled */ + if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_TXDMAEN)) + { + /* Enable Tx DMA Request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + } + + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pData a 16-bit pointer to the Receive data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 24-bit or 32-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size) +{ + uint32_t tmpreg_cfgr; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State != HAL_I2S_STATE_READY) + { + __HAL_UNLOCK(hi2s); + return HAL_BUSY; + } + + /* Set state and reset error code */ + hi2s->State = HAL_I2S_STATE_BUSY_RX; + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->pRxBuffPtr = pData; + + tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + + if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B)) + { + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + /* Set the I2S Rx DMA Half transfer complete callback */ + hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt; + + /* Set the I2S Rx DMA transfer complete callback */ + hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt; + + /* Set the DMA error callback */ + hi2s->hdmarx->XferErrorCallback = I2S_DMAError; + + /* Check if Master Receiver mode is selected */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) + { + /* Clear the Overrun Flag by a read operation to the SPI_DR register followed by a read + access to the SPI_SR register. */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + } + + /* Enable the Rx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, (uint32_t)hi2s->pRxBuffPtr, + hi2s->RxXferSize)) + { + /* Update SPI error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + hi2s->State = HAL_I2S_STATE_READY; + + __HAL_UNLOCK(hi2s); + return HAL_ERROR; + } + + /* Check if the I2S is already enabled */ + if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + /* Check if the I2S Rx request is already enabled */ + if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_RXDMAEN)) + { + /* Enable Rx DMA Request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + } + + __HAL_UNLOCK(hi2s); + return HAL_OK; +} + +/** + * @brief Pauses the audio DMA Stream/Channel playing from the Media. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s) +{ + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State == HAL_I2S_STATE_BUSY_TX) + { + /* Disable the I2S DMA Tx request */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + } + else if (hi2s->State == HAL_I2S_STATE_BUSY_RX) + { + /* Disable the I2S DMA Rx request */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + } +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + else if (hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) + { + /* Pause the audio file playing by disabling the I2S DMA request */ + CLEAR_BIT(hi2s->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN)); + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN)); + } +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + else + { + /* nothing to do */ + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2s); + + return HAL_OK; +} + +/** + * @brief Resumes the audio DMA Stream/Channel playing from the Media. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s) +{ + /* Process Locked */ + __HAL_LOCK(hi2s); + + if (hi2s->State == HAL_I2S_STATE_BUSY_TX) + { + /* Enable the I2S DMA Tx request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + } + else if (hi2s->State == HAL_I2S_STATE_BUSY_RX) + { + /* Enable the I2S DMA Rx request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + } +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + else if (hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) + { + /* Pause the audio file playing by disabling the I2S DMA request */ + SET_BIT(hi2s->Instance->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN)); + SET_BIT(I2SxEXT(hi2s->Instance)->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN)); + + /* If the I2Sext peripheral is still not enabled, enable it */ + if ((I2SxEXT(hi2s->Instance)->I2SCFGR & SPI_I2SCFGR_I2SE) == 0U) + { + /* Enable I2Sext peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + } + } +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + else + { + /* nothing to do */ + } + + /* If the I2S peripheral is still not enabled, enable it */ + if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE)) + { + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hi2s); + + return HAL_OK; +} + +/** + * @brief Stops the audio DMA Stream/Channel playing from the Media. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s) +{ +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + uint32_t tickstart; +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + HAL_StatusTypeDef errorcode = HAL_OK; + /* The Lock is not implemented on this API to allow the user application + to call the HAL SPI API under callbacks HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback() + when calling HAL_DMA_Abort() API the DMA TX or RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback() + */ + + if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)) + { + /* Abort the I2S DMA tx Stream/Channel */ + if (hi2s->hdmatx != NULL) + { + /* Disable the I2S DMA tx Stream/Channel */ + if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx)) + { + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + + /* Wait until TXE flag is set */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, I2S_TIMEOUT_FLAG) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + + /* Wait until BSY flag is Reset */ + if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, I2S_TIMEOUT_FLAG) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + + /* Disable I2S peripheral */ + __HAL_I2S_DISABLE(hi2s); + + /* Clear UDR flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Disable the I2S Tx DMA requests */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + + if (hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) + { + /* Abort the I2S DMA rx Stream/Channel */ + if (hi2s->hdmarx != NULL) + { + /* Disable the I2S DMA rx Stream/Channel */ + if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx)) + { + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + + /* Disable I2Sext peripheral */ + __HAL_I2SEXT_DISABLE(hi2s); + + /* Clear OVR flag */ + __HAL_I2SEXT_CLEAR_OVRFLAG(hi2s); + + /* Disable the I2SxEXT DMA request */ + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_RXDMAEN); + + if (hi2s->Init.Mode == I2S_MODE_SLAVE_TX) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_BUSY_LINE_RX); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + else + { + /* Read DR to Flush RX Data */ + READ_REG(I2SxEXT(hi2s->Instance)->DR); + } + } +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + } + + else if ((hi2s->Init.Mode == I2S_MODE_MASTER_RX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)) + { + /* Abort the I2S DMA rx Stream/Channel */ + if (hi2s->hdmarx != NULL) + { + /* Disable the I2S DMA rx Stream/Channel */ + if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx)) + { + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + errorcode = HAL_ERROR; + } + } +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + + if (hi2s->State == HAL_I2S_STATE_BUSY_TX_RX) + { + /* Abort the I2S DMA tx Stream/Channel */ + if (hi2s->hdmatx != NULL) + { + /* Disable the I2S DMA tx Stream/Channel */ + if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx)) + { + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + + tickstart = HAL_GetTick(); + + /* Wait until TXE flag is set */ + while (__HAL_I2SEXT_GET_FLAG(hi2s, I2S_FLAG_TXE) != SET) + { + if (((HAL_GetTick() - tickstart) > I2S_TIMEOUT_FLAG)) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + } + + /* Wait until BSY flag is Reset */ + while (__HAL_I2SEXT_GET_FLAG(hi2s, I2S_FLAG_BSY) != RESET) + { + if (((HAL_GetTick() - tickstart) > I2S_TIMEOUT_FLAG)) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + } + + /* Disable I2Sext peripheral */ + __HAL_I2SEXT_DISABLE(hi2s); + + /* Clear UDR flag */ + __HAL_I2SEXT_CLEAR_UDRFLAG(hi2s); + + /* Disable the I2SxEXT DMA request */ + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_TXDMAEN); + } +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + + /* Disable I2S peripheral */ + __HAL_I2S_DISABLE(hi2s); + + /* Clear OVR flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Disable the I2S Rx DMA request */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + + if (hi2s->Init.Mode == I2S_MODE_SLAVE_RX) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_BUSY_LINE_RX); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + errorcode = HAL_ERROR; + } + else + { + /* Read DR to Flush RX Data */ + READ_REG((hi2s->Instance)->DR); + } + } + + hi2s->State = HAL_I2S_STATE_READY; + + return errorcode; +} + +/** + * @brief This function handles I2S interrupt request. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s) +{ + /* Call the IrqHandler ISR set during HAL_I2S_INIT */ + hi2s->IrqHandlerISR(hi2s); +} + +/** + * @brief Tx Transfer Half completed callbacks + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Transfer completed callbacks + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer half completed callbacks + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief I2S error callbacks + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +__weak void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2S_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup I2S_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the I2S state + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval HAL state + */ +HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s) +{ + return hi2s->State; +} + +/** + * @brief Return the I2S error code + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval I2S Error Code + */ +uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s) +{ + return hi2s->ErrorCode; +} +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2S_Private_Functions I2S Private Functions + * @{ + */ +/** + * @brief DMA I2S 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 I2S_DMATxCplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* if DMA is configured in DMA_NORMAL Mode */ + if (hdma->Init.Mode == DMA_NORMAL) + { + /* Disable Tx DMA Request */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + + hi2s->TxXferCount = 0U; + hi2s->State = HAL_I2S_STATE_READY; + } + /* Call user Tx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxCpltCallback(hi2s); +#else + HAL_I2S_TxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S 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 I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Call user Tx half complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxHalfCpltCallback(hi2s); +#else + HAL_I2S_TxHalfCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S 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 I2S_DMARxCplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* if DMA is configured in DMA_NORMAL Mode */ + if (hdma->Init.Mode == DMA_NORMAL) + { + /* Disable Rx DMA Request */ + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + hi2s->RxXferCount = 0U; + hi2s->State = HAL_I2S_STATE_READY; + } + /* Call user Rx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->RxCpltCallback(hi2s); +#else + HAL_I2S_RxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S 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 I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Call user Rx half complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->RxHalfCpltCallback(hi2s); +#else + HAL_I2S_RxHalfCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S 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 I2S_DMAError(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */ + + /* Disable Rx and Tx DMA Request */ + CLEAR_BIT(hi2s->Instance->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN)); + hi2s->TxXferCount = 0U; + hi2s->RxXferCount = 0U; + + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief Transmit an amount of data in non-blocking mode with Interrupt + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s) +{ + /* Transmit data */ + hi2s->Instance->DR = (*hi2s->pTxBuffPtr); + hi2s->pTxBuffPtr++; + hi2s->TxXferCount--; + + if (hi2s->TxXferCount == 0U) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + hi2s->State = HAL_I2S_STATE_READY; + /* Call user Tx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxCpltCallback(hi2s); +#else + HAL_I2S_TxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Receive an amount of data in non-blocking mode with Interrupt + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s) +{ + /* Receive data */ + (*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR; + hi2s->pRxBuffPtr++; + hi2s->RxXferCount--; + + if (hi2s->RxXferCount == 0U) + { + /* Disable RXNE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + hi2s->State = HAL_I2S_STATE_READY; + /* Call user Rx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->RxCpltCallback(hi2s); +#else + HAL_I2S_RxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } +} + +/** + * @brief This function handles I2S interrupt request. + * @param hi2s: pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @retval None + */ +static void I2S_IRQHandler(I2S_HandleTypeDef *hi2s) +{ + __IO uint32_t i2ssr = hi2s->Instance->SR; + + if (hi2s->State == HAL_I2S_STATE_BUSY_RX) + { + /* I2S in mode Receiver ------------------------------------------------*/ + if (((i2ssr & I2S_FLAG_RXNE) == I2S_FLAG_RXNE) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_RXNE) != RESET)) + { + I2S_Receive_IT(hi2s); + } + + /* I2S Overrun error interrupt occurred -------------------------------------*/ + if (((i2ssr & I2S_FLAG_OVR) == I2S_FLAG_OVR) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR) != RESET)) + { + /* Disable RXNE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Clear Overrun flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } + + if (hi2s->State == HAL_I2S_STATE_BUSY_TX) + { + /* I2S in mode Transmitter -----------------------------------------------*/ + if (((i2ssr & I2S_FLAG_TXE) == I2S_FLAG_TXE) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_TXE) != RESET)) + { + I2S_Transmit_IT(hi2s); + } + + /* I2S Underrun error interrupt occurred --------------------------------*/ + if (((i2ssr & I2S_FLAG_UDR) == I2S_FLAG_UDR) && (__HAL_I2S_GET_IT_SOURCE(hi2s, I2S_IT_ERR) != RESET)) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Clear Underrun flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief This function handles I2S Communication Timeout. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param Flag Flag checked + * @param State Value of the flag expected + * @param Timeout Duration of the timeout + * @retval HAL status + */ +static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State, + uint32_t Timeout) +{ + uint32_t tickstart; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until flag is set to status*/ + while (((__HAL_I2S_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State) + { + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2s); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_I2S_MODULE_ENABLED */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c new file mode 100644 index 0000000..643bf74 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_i2s_ex.c @@ -0,0 +1,1135 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_i2s_ex.c + * @author MCD Application Team + * @brief I2S HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of I2S extension peripheral: + * + Extension features 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 + ============================================================================== + ##### I2S Extension features ##### + ============================================================================== + [..] + (#) In I2S full duplex mode, each SPI peripheral is able to manage sending and receiving + data simultaneously using two data lines. Each SPI peripheral has an extended block + called I2Sxext (i.e I2S2ext for SPI2 and I2S3ext for SPI3). + (#) The extension block is not a full SPI IP, it is used only as I2S slave to + implement full duplex mode. The extension block uses the same clock sources + as its master. + + (#) Both I2Sx and I2Sx_ext can be configured as transmitters or receivers. + + [..] + (@) Only I2Sx can deliver SCK and WS to I2Sx_ext in full duplex mode, where + I2Sx can be I2S2 or I2S3. + + ##### How to use this driver ##### + =============================================================================== + [..] + Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send and receive in the same time an amount of data in blocking mode using HAL_I2SEx_TransmitReceive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send and receive in the same time an amount of data in non blocking mode using HAL_I2SEx_TransmitReceive_IT() + (+) At transmission/reception end of transfer HAL_I2SEx_TxRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2SEx_TxRxCpltCallback + (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2S_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send and receive an amount of data in non blocking mode (DMA) using HAL_I2SEx_TransmitReceive_DMA() + (+) At transmission/reception end of transfer HAL_I2SEx_TxRxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_I2S_TxRxCpltCallback + (+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_I2S_ErrorCallback + (+) __HAL_I2SEXT_FLUSH_RX_DR: In Full-Duplex Slave mode, if HAL_I2S_DMAStop is used to stop the + communication, an error HAL_I2S_ERROR_BUSY_LINE_RX is raised as the master continue to transmit data. + In this case __HAL_I2SEXT_FLUSH_RX_DR macro must be used to flush the remaining data + inside I2Sx and I2Sx_ext DR registers and avoid using DeInit/Init process for the next transfer. + @endverbatim + + Additional Figure: The Extended block uses the same clock sources as its master. + + +-----------------------+ + I2Sx_SCK | | + ----------+-->| I2Sx |------------------->I2Sx_SD(in/out) + +--|-->| | + | | +-----------------------+ + | | + I2S_WS | | + ------>| | + | | +-----------------------+ + | +-->| | + | | I2Sx_ext |------------------->I2Sx_extSD(in/out) + +----->| | + +-----------------------+ + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_I2S_MODULE_ENABLED + +/** @defgroup I2SEx I2SEx + * @brief I2S Extended HAL module driver + * @{ + */ + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) + +/* Private typedef -----------------------------------------------------------*/ +/** @defgroup I2SEx_Private_Typedef I2S Extended Private Typedef + * @{ + */ +typedef enum +{ + I2S_USE_I2S = 0x00U, /*!< I2Sx should be used */ + I2S_USE_I2SEXT = 0x01U, /*!< I2Sx_ext should be used */ +} I2S_UseTypeDef; +/** + * @} + */ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup I2SEx_Private_Functions I2S Extended Private Functions + * @{ + */ +static void I2SEx_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma); +static void I2SEx_TxRxDMACplt(DMA_HandleTypeDef *hdma); +static void I2SEx_TxRxDMAError(DMA_HandleTypeDef *hdma); +static void I2SEx_RxISR_I2S(I2S_HandleTypeDef *hi2s); +static void I2SEx_RxISR_I2SExt(I2S_HandleTypeDef *hi2s); +static void I2SEx_TxISR_I2S(I2S_HandleTypeDef *hi2s); +static void I2SEx_TxISR_I2SExt(I2S_HandleTypeDef *hi2s); +static HAL_StatusTypeDef I2SEx_FullDuplexWaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, + uint32_t Flag, + uint32_t State, + uint32_t Timeout, + I2S_UseTypeDef i2sUsed); +/** + * @} + */ + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup I2SEx I2SEx + * @{ + */ + +/** @addtogroup I2SEx_Exported_Functions I2S Extended Exported Functions + * @{ + */ + +/** @defgroup I2SEx_Exported_Functions_Group1 I2S Extended IO operation functions + * @brief I2SEx IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the I2S data + transfers. + + (#) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_I2SEx_TransmitReceive() + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_I2SEx_TransmitReceive_IT() + (++) HAL_I2SEx_FullDuplex_IRQHandler() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_I2SEx_TransmitReceive_DMA() + + (#) A set of Transfer Complete Callback are provided in non Blocking mode: + (++) HAL_I2SEx_TxRxCpltCallback() +@endverbatim + * @{ + */ +/** + * @brief Full-Duplex Transmit/Receive data in blocking mode. + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pTxData a 16-bit pointer to the Transmit data buffer. + * @param pRxData a 16-bit pointer to the Receive data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 16-bit data length. + * @param Timeout Timeout duration + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive(I2S_HandleTypeDef *hi2s, + uint16_t *pTxData, + uint16_t *pRxData, + uint16_t Size, + uint32_t Timeout) +{ + uint32_t tmp1 = 0U; + HAL_StatusTypeDef errorcode = HAL_OK; + + if (hi2s->State != HAL_I2S_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended + is selected during the I2S configuration phase, the Size parameter means the number + of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data + frame is selected the Size parameter means the number of 16-bit data length. */ + if ((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + /* Set state and reset error code */ + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; + + tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; + /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ + if ((tmp1 == I2S_MODE_MASTER_TX) || (tmp1 == I2S_MODE_SLAVE_TX)) + { + /* Prepare the First Data before enabling the I2S */ + hi2s->Instance->DR = (*pTxData++); + hi2s->TxXferCount--; + + /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + + /* Enable I2Sx peripheral */ + __HAL_I2S_ENABLE(hi2s); + + /* Check if Master Receiver mode is selected */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) + { + /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read + access to the SPI_SR register. */ + __HAL_I2SEXT_CLEAR_OVRFLAG(hi2s); + } + + while ((hi2s->RxXferCount > 0U) || (hi2s->TxXferCount > 0U)) + { + if (hi2s->TxXferCount > 0U) + { + /* Wait until TXE flag is set */ + if (I2SEx_FullDuplexWaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout, I2S_USE_I2S) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + errorcode = HAL_ERROR; + goto error; + } + /* Write Data on DR register */ + hi2s->Instance->DR = (*pTxData++); + hi2s->TxXferCount--; + + /* Check if an underrun occurs */ + if ((__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET) && (tmp1 == I2S_MODE_SLAVE_TX)) + { + /* Clear Underrun flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + } + } + if (hi2s->RxXferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2SEx_FullDuplexWaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout, I2S_USE_I2SEXT) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + errorcode = HAL_ERROR; + goto error; + } + /* Read Data from DR register */ + (*pRxData++) = I2SxEXT(hi2s->Instance)->DR; + hi2s->RxXferCount--; + + /* Check if an overrun occurs */ + if (__HAL_I2SEXT_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET) + { + /* Clear Overrun flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + } + } + } + } + /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ + else + { + /* Prepare the First Data before enabling the I2S */ + I2SxEXT(hi2s->Instance)->DR = (*pTxData++); + hi2s->TxXferCount--; + + /* Enable I2Sext(transmitter) after enabling I2Sx peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + + /* Enable I2S peripheral before the I2Sext*/ + __HAL_I2S_ENABLE(hi2s); + + /* Check if Master Receiver mode is selected */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) + { + /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read + access to the SPI_SR register. */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + } + + while ((hi2s->RxXferCount > 0U) || (hi2s->TxXferCount > 0U)) + { + if (hi2s->TxXferCount > 0U) + { + /* Wait until TXE flag is set */ + if (I2SEx_FullDuplexWaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout, I2S_USE_I2SEXT) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + errorcode = HAL_ERROR; + goto error; + } + /* Write Data on DR register */ + I2SxEXT(hi2s->Instance)->DR = (*pTxData++); + hi2s->TxXferCount--; + + /* Check if an underrun occurs */ + if ((__HAL_I2SEXT_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET) && (tmp1 == I2S_MODE_SLAVE_RX)) + { + /* Clear Underrun flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + } + } + if (hi2s->RxXferCount > 0U) + { + /* Wait until RXNE flag is set */ + if (I2SEx_FullDuplexWaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout, I2S_USE_I2S) != HAL_OK) + { + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT); + errorcode = HAL_ERROR; + goto error; + } + /* Read Data from DR register */ + (*pRxData++) = hi2s->Instance->DR; + hi2s->RxXferCount--; + + /* Check if an overrun occurs */ + if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET) + { + /* Clear Overrun flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Set the error code */ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + } + } + } + } + + if (hi2s->ErrorCode != HAL_I2S_ERROR_NONE) + { + errorcode = HAL_ERROR; + } + +error : + hi2s->State = HAL_I2S_STATE_READY; + __HAL_UNLOCK(hi2s); + return errorcode; +} + +/** + * @brief Full-Duplex Transmit/Receive data in non-blocking mode using Interrupt + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pTxData a 16-bit pointer to the Transmit data buffer. + * @param pRxData a 16-bit pointer to the Receive data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 16-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_IT(I2S_HandleTypeDef *hi2s, + uint16_t *pTxData, + uint16_t *pRxData, + uint16_t Size) +{ + uint32_t tmp1 = 0U; + HAL_StatusTypeDef errorcode = HAL_OK; + + if (hi2s->State != HAL_I2S_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + hi2s->pTxBuffPtr = pTxData; + hi2s->pRxBuffPtr = pRxData; + + tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended + is selected during the I2S configuration phase, the Size parameter means the number + of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data + frame is selected the Size parameter means the number of 16-bit data length. */ + if ((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; + + /* Set the function for IT treatment */ + if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)) + { + /* Enable I2Sext RXNE and ERR interrupts */ + __HAL_I2SEXT_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Enable I2Sx TXE and ERR interrupts */ + __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Transmit First data */ + hi2s->Instance->DR = (*hi2s->pTxBuffPtr++); + hi2s->TxXferCount--; + + if (hi2s->TxXferCount == 0U) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + } + } + else /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ + { + /* Enable I2Sext TXE and ERR interrupts */ + __HAL_I2SEXT_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Enable I2Sext RXNE and ERR interrupts */ + __HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Transmit First data */ + I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); + hi2s->TxXferCount--; + + if (hi2s->TxXferCount == 0U) + { + /* Disable I2Sext TXE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + } + } + + /* Enable I2Sext peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + + /* Enable I2S peripheral */ + __HAL_I2S_ENABLE(hi2s); + +error : + __HAL_UNLOCK(hi2s); + return errorcode; +} + +/** + * @brief Full-Duplex Transmit/Receive data in non-blocking mode using DMA + * @param hi2s pointer to a I2S_HandleTypeDef structure that contains + * the configuration information for I2S module + * @param pTxData a 16-bit pointer to the Transmit data buffer. + * @param pRxData a 16-bit pointer to the Receive data buffer. + * @param Size number of data sample to be sent: + * @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S + * configuration phase, the Size parameter means the number of 16-bit data length + * in the transaction and when a 24-bit data frame or a 32-bit data frame is selected + * the Size parameter means the number of 16-bit data length. + * @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization + * between Master and Slave(example: audio streaming). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_I2SEx_TransmitReceive_DMA(I2S_HandleTypeDef *hi2s, + uint16_t *pTxData, + uint16_t *pRxData, + uint16_t Size) +{ + uint32_t *tmp = NULL; + uint32_t tmp1 = 0U; + HAL_StatusTypeDef errorcode = HAL_OK; + + if (hi2s->State != HAL_I2S_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hi2s); + + hi2s->pTxBuffPtr = pTxData; + hi2s->pRxBuffPtr = pRxData; + + tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN); + /* Check the Data format: When a 16-bit data frame or a 16-bit data frame extended + is selected during the I2S configuration phase, the Size parameter means the number + of 16-bit data length in the transaction and when a 24-bit data frame or a 32-bit data + frame is selected the Size parameter means the number of 16-bit data length. */ + if ((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B)) + { + hi2s->TxXferSize = (Size << 1U); + hi2s->TxXferCount = (Size << 1U); + hi2s->RxXferSize = (Size << 1U); + hi2s->RxXferCount = (Size << 1U); + } + else + { + hi2s->TxXferSize = Size; + hi2s->TxXferCount = Size; + hi2s->RxXferSize = Size; + hi2s->RxXferCount = Size; + } + + hi2s->ErrorCode = HAL_I2S_ERROR_NONE; + hi2s->State = HAL_I2S_STATE_BUSY_TX_RX; + + /* Set the I2S Rx DMA Half transfer complete callback */ + hi2s->hdmarx->XferHalfCpltCallback = I2SEx_TxRxDMAHalfCplt; + + /* Set the I2S Rx DMA transfer complete callback */ + hi2s->hdmarx->XferCpltCallback = I2SEx_TxRxDMACplt; + + /* Set the I2S Rx DMA error callback */ + hi2s->hdmarx->XferErrorCallback = I2SEx_TxRxDMAError; + + /* Set the I2S Tx DMA Half transfer complete callback as NULL */ + hi2s->hdmatx->XferHalfCpltCallback = NULL; + + /* Set the I2S Tx DMA transfer complete callback as NULL */ + hi2s->hdmatx->XferCpltCallback = NULL; + + /* Set the I2S Tx DMA error callback */ + hi2s->hdmatx->XferErrorCallback = I2SEx_TxRxDMAError; + + tmp1 = hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG; + /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ + if ((tmp1 == I2S_MODE_MASTER_TX) || (tmp1 == I2S_MODE_SLAVE_TX)) + { + /* Enable the Rx DMA Stream */ + tmp = (uint32_t *)&pRxData; + HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, *(uint32_t *)tmp, hi2s->RxXferSize); + + /* Enable Rx DMA Request */ + SET_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_RXDMAEN); + + /* Enable the Tx DMA Stream */ + tmp = (uint32_t *)&pTxData; + HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t *)tmp, (uint32_t)&hi2s->Instance->DR, hi2s->TxXferSize); + + /* Enable Tx DMA Request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2Sext(receiver) before enabling I2Sx peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + + /* Enable I2S peripheral after the I2Sext */ + __HAL_I2S_ENABLE(hi2s); + } + } + else + { + /* Check if Master Receiver mode is selected */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX) + { + /* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read + access to the SPI_SR register. */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + } + /* Enable the Tx DMA Stream */ + tmp = (uint32_t *)&pTxData; + HAL_DMA_Start_IT(hi2s->hdmatx, *(uint32_t *)tmp, (uint32_t)&I2SxEXT(hi2s->Instance)->DR, hi2s->TxXferSize); + + /* Enable Tx DMA Request */ + SET_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_TXDMAEN); + + /* Enable the Rx DMA Stream */ + tmp = (uint32_t *)&pRxData; + HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, *(uint32_t *)tmp, hi2s->RxXferSize); + + /* Enable Rx DMA Request */ + SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + + /* Check if the I2S is already enabled */ + if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE) + { + /* Enable I2Sext(transmitter) before enabling I2Sx peripheral */ + __HAL_I2SEXT_ENABLE(hi2s); + /* Enable I2S peripheral before the I2Sext */ + __HAL_I2S_ENABLE(hi2s); + } + } + +error : + __HAL_UNLOCK(hi2s); + return errorcode; +} + +/** + * @brief This function handles I2S/I2Sext interrupt requests in full-duplex mode. + * @param hi2s I2S handle + * @retval HAL status + */ +void HAL_I2SEx_FullDuplex_IRQHandler(I2S_HandleTypeDef *hi2s) +{ + __IO uint32_t i2ssr = hi2s->Instance->SR; + __IO uint32_t i2sextsr = I2SxEXT(hi2s->Instance)->SR; + __IO uint32_t i2scr2 = hi2s->Instance->CR2; + __IO uint32_t i2sextcr2 = I2SxEXT(hi2s->Instance)->CR2; + + /* Check if the I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX Mode is selected */ + if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX)) + { + /* I2S in mode Transmitter -------------------------------------------------*/ + if (((i2ssr & I2S_FLAG_TXE) == I2S_FLAG_TXE) && ((i2scr2 & I2S_IT_TXE) != RESET)) + { + /* When the I2S mode is configured as I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX, + the I2S TXE interrupt will be generated to manage the full-duplex transmit phase. */ + I2SEx_TxISR_I2S(hi2s); + } + + /* I2Sext in mode Receiver -----------------------------------------------*/ + if (((i2sextsr & I2S_FLAG_RXNE) == I2S_FLAG_RXNE) && ((i2sextcr2 & I2S_IT_RXNE) != RESET)) + { + /* When the I2S mode is configured as I2S_MODE_MASTER_TX or I2S_MODE_SLAVE_TX, + the I2Sext RXNE interrupt will be generated to manage the full-duplex receive phase. */ + I2SEx_RxISR_I2SExt(hi2s); + } + + /* I2Sext Overrun error interrupt occurred --------------------------------*/ + if (((i2sextsr & I2S_FLAG_OVR) == I2S_FLAG_OVR) && ((i2sextcr2 & I2S_IT_ERR) != RESET)) + { + /* Disable RXNE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Clear Overrun flag */ + __HAL_I2S_CLEAR_OVRFLAG(hi2s); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + + /* I2S Underrun error interrupt occurred ----------------------------------*/ + if (((i2ssr & I2S_FLAG_UDR) == I2S_FLAG_UDR) && ((i2scr2 & I2S_IT_ERR) != RESET)) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Disable RXNE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Clear underrun flag */ + __HAL_I2S_CLEAR_UDRFLAG(hi2s); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } + /* The I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX Mode is selected */ + else + { + /* I2Sext in mode Transmitter ----------------------------------------------*/ + if (((i2sextsr & I2S_FLAG_TXE) == I2S_FLAG_TXE) && ((i2sextcr2 & I2S_IT_TXE) != RESET)) + { + /* When the I2S mode is configured as I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX, + the I2Sext TXE interrupt will be generated to manage the full-duplex transmit phase. */ + I2SEx_TxISR_I2SExt(hi2s); + } + + /* I2S in mode Receiver --------------------------------------------------*/ + if (((i2ssr & I2S_FLAG_RXNE) == I2S_FLAG_RXNE) && ((i2scr2 & I2S_IT_RXNE) != RESET)) + { + /* When the I2S mode is configured as I2S_MODE_MASTER_RX or I2S_MODE_SLAVE_RX, + the I2S RXNE interrupt will be generated to manage the full-duplex receive phase. */ + I2SEx_RxISR_I2S(hi2s); + } + + /* I2S Overrun error interrupt occurred -------------------------------------*/ + if (((i2ssr & I2S_FLAG_OVR) == I2S_FLAG_OVR) && ((i2scr2 & I2S_IT_ERR) != RESET)) + { + /* Disable RXNE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Disable TXE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + + /* I2Sext Underrun error interrupt occurred -------------------------------*/ + if (((i2sextsr & I2S_FLAG_UDR) == I2S_FLAG_UDR) && ((i2sextcr2 & I2S_IT_ERR) != RESET)) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + /* Disable RXNE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief Tx and Rx Transfer half completed callback + * @param hi2s I2S handle + * @retval None + */ +__weak void HAL_I2SEx_TxRxHalfCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_I2SEx_TxRxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx and Rx Transfer completed callback + * @param hi2s I2S handle + * @retval None + */ +__weak void HAL_I2SEx_TxRxCpltCallback(I2S_HandleTypeDef *hi2s) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hi2s); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_I2SEx_TxRxCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2SEx_Private_Functions I2S Extended Private Functions + * @{ + */ + +/** + * @brief DMA I2S transmit 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 I2SEx_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Call user TxRx Half complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxHalfCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxHalfCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S transmit 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 I2SEx_TxRxDMACplt(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* If DMA is configured in DMA_NORMAL mode */ + if (hdma->Init.Mode == DMA_NORMAL) + { + if (((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) || \ + ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX)) + /* Disable Tx & Rx DMA Requests */ + { + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_RXDMAEN); + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN); + } + else + { + CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN); + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, SPI_CR2_TXDMAEN); + } + + hi2s->RxXferCount = 0U; + hi2s->TxXferCount = 0U; + + hi2s->State = HAL_I2S_STATE_READY; + } + + /* Call user TxRx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA I2S communication error callback + * @param hdma DMA handle + * @retval None + */ +static void I2SEx_TxRxDMAError(DMA_HandleTypeDef *hdma) +{ + I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Rx and Tx DMA Request */ + CLEAR_BIT(hi2s->Instance->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN)); + CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN)); + + hi2s->TxXferCount = 0U; + hi2s->RxXferCount = 0U; + + hi2s->State = HAL_I2S_STATE_READY; + + /* Set the error code and execute error callback*/ + SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA); + /* Call user error callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->ErrorCallback(hi2s); +#else + HAL_I2S_ErrorCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ +} + +/** + * @brief I2S Full-Duplex IT handler transmit function + * @param hi2s I2S handle + * @retval None + */ +static void I2SEx_TxISR_I2S(I2S_HandleTypeDef *hi2s) +{ + /* Write Data on DR register */ + hi2s->Instance->DR = (*hi2s->pTxBuffPtr++); + hi2s->TxXferCount--; + + if (hi2s->TxXferCount == 0U) + { + /* Disable TXE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + if (hi2s->RxXferCount == 0U) + { + hi2s->State = HAL_I2S_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief I2SExt Full-Duplex IT handler transmit function + * @param hi2s I2S handle + * @retval None + */ +static void I2SEx_TxISR_I2SExt(I2S_HandleTypeDef *hi2s) +{ + /* Write Data on DR register */ + I2SxEXT(hi2s->Instance)->DR = (*hi2s->pTxBuffPtr++); + hi2s->TxXferCount--; + + if (hi2s->TxXferCount == 0U) + { + /* Disable I2Sext TXE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR)); + + if (hi2s->RxXferCount == 0U) + { + hi2s->State = HAL_I2S_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief I2S Full-Duplex IT handler receive function + * @param hi2s I2S handle + * @retval None + */ +static void I2SEx_RxISR_I2S(I2S_HandleTypeDef *hi2s) +{ + /* Read Data from DR register */ + (*hi2s->pRxBuffPtr++) = hi2s->Instance->DR; + hi2s->RxXferCount--; + + if (hi2s->RxXferCount == 0U) + { + /* Disable RXNE and ERR interrupt */ + __HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + if (hi2s->TxXferCount == 0U) + { + hi2s->State = HAL_I2S_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief I2SExt Full-Duplex IT handler receive function + * @param hi2s I2S handle + * @retval None + */ +static void I2SEx_RxISR_I2SExt(I2S_HandleTypeDef *hi2s) +{ + /* Read Data from DR register */ + (*hi2s->pRxBuffPtr++) = I2SxEXT(hi2s->Instance)->DR; + hi2s->RxXferCount--; + + if (hi2s->RxXferCount == 0U) + { + /* Disable I2Sext RXNE and ERR interrupt */ + __HAL_I2SEXT_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR)); + + if (hi2s->TxXferCount == 0U) + { + hi2s->State = HAL_I2S_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U) + hi2s->TxRxCpltCallback(hi2s); +#else + HAL_I2SEx_TxRxCpltCallback(hi2s); +#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief This function handles I2S Communication Timeout. + * @param hi2s I2S handle + * @param Flag Flag checked + * @param State Value of the flag expected + * @param Timeout Duration of the timeout + * @param i2sUsed I2S instance reference + * @retval HAL status + */ +static HAL_StatusTypeDef I2SEx_FullDuplexWaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, + uint32_t Flag, + uint32_t State, + uint32_t Timeout, + I2S_UseTypeDef i2sUsed) +{ + uint32_t tickstart = HAL_GetTick(); + + if (i2sUsed == I2S_USE_I2S) + { + /* Wait until flag is reset */ + while (((__HAL_I2S_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2s); + + return HAL_TIMEOUT; + } + } + } + } + else /* i2sUsed == I2S_USE_I2SEXT */ + { + /* Wait until flag is reset */ + while (((__HAL_I2SEXT_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + /* Set the I2S State ready */ + hi2s->State = HAL_I2S_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hi2s); + + return HAL_TIMEOUT; + } + } + } + } + return HAL_OK; +} + +/** + * @} + */ +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + +/** + * @} + */ +#endif /* HAL_I2S_MODULE_ENABLED */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c new file mode 100644 index 0000000..c754d46 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_irda.c @@ -0,0 +1,2687 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_irda.c + * @author MCD Application Team + * @brief IRDA HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the IrDA SIR ENDEC block (IrDA): + * + 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 IRDA HAL driver can be used as follows: + + (#) Declare a IRDA_HandleTypeDef handle structure (eg. IRDA_HandleTypeDef hirda). + (#) Initialize the IRDA low level resources by implementing the HAL_IRDA_MspInit() API: + (##) Enable the USARTx interface clock. + (##) IRDA pins configuration: + (+++) Enable the clock for the IRDA GPIOs. + (+++) Configure IRDA pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_IRDA_Transmit_IT() + and HAL_IRDA_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_IRDA_Transmit_DMA() + and HAL_IRDA_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx stream. + (+++) Associate the initialized DMA handle to the IRDA DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx stream. + (+++) Configure the IRDAx 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, Parity, IrDA Mode, Prescaler + and Mode(Receiver/Transmitter) in the hirda Init structure. + + (#) Initialize the IRDA registers by calling the HAL_IRDA_Init() API: + (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_IRDA_MspInit() API. + + -@@- The specific IRDA interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_IRDA_ENABLE_IT() and __HAL_IRDA_DISABLE_IT() inside the transmit and receive process. + + (#) Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_IRDA_Transmit() + (+) Receive an amount of data in blocking mode using HAL_IRDA_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_IRDA_Transmit_IT() + (+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_IRDA_Receive_IT() + (+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_RxCpltCallback + (+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_IRDA_ErrorCallback + + *** DMA mode IO operation *** + ============================= + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_IRDA_Transmit_DMA() + (+) At transmission end of half transfer HAL_IRDA_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_TxHalfCpltCallback + (+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_IRDA_Receive_DMA() + (+) At reception end of half transfer HAL_IRDA_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_RxHalfCpltCallback + (+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_IRDA_RxCpltCallback + (+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_IRDA_ErrorCallback + (+) Pause the DMA Transfer using HAL_IRDA_DMAPause() + (+) Resume the DMA Transfer using HAL_IRDA_DMAResume() + (+) Stop the DMA Transfer using HAL_IRDA_DMAStop() + + *** IRDA HAL driver macros list *** + =================================== + [..] + Below the list of most used macros in IRDA HAL driver. + + (+) __HAL_IRDA_ENABLE: Enable the IRDA peripheral + (+) __HAL_IRDA_DISABLE: Disable the IRDA peripheral + (+) __HAL_IRDA_GET_FLAG : Check whether the specified IRDA flag is set or not + (+) __HAL_IRDA_CLEAR_FLAG : Clear the specified IRDA pending flag + (+) __HAL_IRDA_ENABLE_IT: Enable the specified IRDA interrupt + (+) __HAL_IRDA_DISABLE_IT: Disable the specified IRDA interrupt + (+) __HAL_IRDA_GET_IT_SOURCE: Check whether the specified IRDA interrupt has occurred or not + + [..] + (@) You can refer to the IRDA HAL driver header file for more useful macros + + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function HAL_IRDA_RegisterCallback() to register a user callback. + Function HAL_IRDA_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 : IRDA MspInit. + (+) MspDeInitCallback : IRDA MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_IRDA_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_IRDA_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 : IRDA MspInit. + (+) MspDeInitCallback : IRDA MspDeInit. + + [..] + By default, after the HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxHalfCpltCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_IRDA_Init() + and HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_IRDA_Init() and HAL_IRDA_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_IRDA_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_IRDA_STATE_READY or HAL_IRDA_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_IRDA_RegisterCallback() before calling HAL_IRDA_DeInit() + or HAL_IRDA_Init() function. + + [..] + When The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + @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 IRDA frame formats are as listed in the following table: + +-------------------------------------------------------------+ + | M bit | PCE bit | IRDA frame | + |---------------------|---------------------------------------| + | 0 | 0 | | SB | 8 bit data | 1 STB | | + |---------|-----------|---------------------------------------| + | 0 | 1 | | SB | 7 bit data | PB | 1 STB | | + |---------|-----------|---------------------------------------| + | 1 | 0 | | SB | 9 bit data | 1 STB | | + |---------|-----------|---------------------------------------| + | 1 | 1 | | SB | 8 bit data | PB | 1 STB | | + +-------------------------------------------------------------+ + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup IRDA IRDA + * @brief HAL IRDA module driver + * @{ + */ + +#ifdef HAL_IRDA_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup IRDA_Private_Functions + * @{ + */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ +static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda); +static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda); +static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda); +static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda); +static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma); +static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma); +static void IRDA_DMAError(DMA_HandleTypeDef *hdma); +static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda); +static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup IRDA_Exported_Functions IrDA Exported Functions + * @{ + */ + +/** @defgroup IRDA_Exported_Functions_Group1 IrDA 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 IrDA mode. + (+) For the asynchronous mode only these parameters can be configured: + (++) BaudRate + (++) WordLength + (++) 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 IRDA frame formats. + (++) Prescaler: A pulse of width less than two and greater than one PSC period(s) may or may + not be rejected. The receiver set up time should be managed by software. The IrDA physical layer + specification specifies a minimum of 10 ms delay between transmission and + reception (IrDA is a half duplex protocol). + (++) Mode: Receiver/transmitter modes + (++) IrDAMode: the IrDA can operate in the Normal mode or in the Low power mode. + [..] + The HAL_IRDA_Init() API follows IRDA configuration procedures (details for the procedures + are available in reference manual). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the IRDA mode according to the specified + * parameters in the IRDA_InitTypeDef and create the associated handle. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_Init(IRDA_HandleTypeDef *hirda) +{ + /* Check the IRDA handle allocation */ + if (hirda == NULL) + { + return HAL_ERROR; + } + + /* Check the IRDA instance parameters */ + assert_param(IS_IRDA_INSTANCE(hirda->Instance)); + /* Check the IRDA mode parameter in the IRDA handle */ + assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode)); + + if (hirda->gState == HAL_IRDA_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hirda->Lock = HAL_UNLOCKED; + +#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1 + IRDA_InitCallbacksToDefault(hirda); + + if (hirda->MspInitCallback == NULL) + { + hirda->MspInitCallback = HAL_IRDA_MspInit; + } + + /* Init the low level hardware */ + hirda->MspInitCallback(hirda); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_IRDA_MspInit(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + } + + hirda->gState = HAL_IRDA_STATE_BUSY; + + /* Disable the IRDA peripheral */ + __HAL_IRDA_DISABLE(hirda); + + /* Set the IRDA communication parameters */ + IRDA_SetConfig(hirda); + + /* 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(hirda->Instance->CR2, (USART_CR2_LINEN | USART_CR2_STOP | USART_CR2_CLKEN)); + CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL)); + + /* Enable the IRDA peripheral */ + __HAL_IRDA_ENABLE(hirda); + + /* Set the prescaler */ + MODIFY_REG(hirda->Instance->GTPR, USART_GTPR_PSC, hirda->Init.Prescaler); + + /* Configure the IrDA mode */ + MODIFY_REG(hirda->Instance->CR3, USART_CR3_IRLP, hirda->Init.IrDAMode); + + /* Enable the IrDA mode by setting the IREN bit in the CR3 register */ + SET_BIT(hirda->Instance->CR3, USART_CR3_IREN); + + /* Initialize the IRDA state*/ + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->gState = HAL_IRDA_STATE_READY; + hirda->RxState = HAL_IRDA_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the IRDA peripheral + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_DeInit(IRDA_HandleTypeDef *hirda) +{ + /* Check the IRDA handle allocation */ + if (hirda == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_IRDA_INSTANCE(hirda->Instance)); + + hirda->gState = HAL_IRDA_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_IRDA_DISABLE(hirda); + + /* DeInit the low level hardware */ +#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1 + if (hirda->MspDeInitCallback == NULL) + { + hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; + } + /* DeInit the low level hardware */ + hirda->MspDeInitCallback(hirda); +#else + HAL_IRDA_MspDeInit(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + + hirda->gState = HAL_IRDA_STATE_RESET; + hirda->RxState = HAL_IRDA_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hirda); + + return HAL_OK; +} + +/** + * @brief IRDA MSP Init. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_MspInit(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_IRDA_MspInit can be implemented in the user file + */ +} + +/** + * @brief IRDA MSP DeInit. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_MspDeInit(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_IRDA_MspDeInit can be implemented in the user file + */ +} + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User IRDA Callback + * To be used instead of the weak predefined callback + * @param hirda irda handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_RegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID, pIRDA_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hirda); + + if (hirda->gState == HAL_IRDA_STATE_READY) + { + switch (CallbackID) + { + case HAL_IRDA_TX_HALFCOMPLETE_CB_ID : + hirda->TxHalfCpltCallback = pCallback; + break; + + case HAL_IRDA_TX_COMPLETE_CB_ID : + hirda->TxCpltCallback = pCallback; + break; + + case HAL_IRDA_RX_HALFCOMPLETE_CB_ID : + hirda->RxHalfCpltCallback = pCallback; + break; + + case HAL_IRDA_RX_COMPLETE_CB_ID : + hirda->RxCpltCallback = pCallback; + break; + + case HAL_IRDA_ERROR_CB_ID : + hirda->ErrorCallback = pCallback; + break; + + case HAL_IRDA_ABORT_COMPLETE_CB_ID : + hirda->AbortCpltCallback = pCallback; + break; + + case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID : + hirda->AbortTransmitCpltCallback = pCallback; + break; + + case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID : + hirda->AbortReceiveCpltCallback = pCallback; + break; + + case HAL_IRDA_MSPINIT_CB_ID : + hirda->MspInitCallback = pCallback; + break; + + case HAL_IRDA_MSPDEINIT_CB_ID : + hirda->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hirda->gState == HAL_IRDA_STATE_RESET) + { + switch (CallbackID) + { + case HAL_IRDA_MSPINIT_CB_ID : + hirda->MspInitCallback = pCallback; + break; + + case HAL_IRDA_MSPDEINIT_CB_ID : + hirda->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hirda); + + return status; +} + +/** + * @brief Unregister an IRDA callback + * IRDA callback is redirected to the weak predefined callback + * @param hirda irda handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_UnRegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hirda); + + if (HAL_IRDA_STATE_READY == hirda->gState) + { + switch (CallbackID) + { + case HAL_IRDA_TX_HALFCOMPLETE_CB_ID : + hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_IRDA_TX_COMPLETE_CB_ID : + hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_IRDA_RX_HALFCOMPLETE_CB_ID : + hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_IRDA_RX_COMPLETE_CB_ID : + hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_IRDA_ERROR_CB_ID : + hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_IRDA_ABORT_COMPLETE_CB_ID : + hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID : + hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + break; + + case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID : + hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + break; + + case HAL_IRDA_MSPINIT_CB_ID : + hirda->MspInitCallback = HAL_IRDA_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_IRDA_MSPDEINIT_CB_ID : + hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_IRDA_STATE_RESET == hirda->gState) + { + switch (CallbackID) + { + case HAL_IRDA_MSPINIT_CB_ID : + hirda->MspInitCallback = HAL_IRDA_MspInit; + break; + + case HAL_IRDA_MSPDEINIT_CB_ID : + hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; + break; + + default : + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hirda); + + return status; +} +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup IRDA_Exported_Functions_Group2 IO operation functions + * @brief IRDA Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the IRDA data transfers. + IrDA is a half duplex communication protocol. If the Transmitter is busy, any data + on the IrDA receive line will be ignored by the IrDA decoder and if the Receiver + is busy, data on the TX from the USART to IrDA will not be encoded by IrDA. + While receiving data, transmission should be avoided as the data to be transmitted + could be corrupted. + + (#) 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 IRDA IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxCpltCallback() user callbacks + will be executed respectively at the end of the Transmit or Receive process + The HAL_IRDA_ErrorCallback() user callback will be executed when a communication error is detected + + (#) Blocking mode APIs are : + (++) HAL_IRDA_Transmit() + (++) HAL_IRDA_Receive() + + (#) Non Blocking mode APIs with Interrupt are : + (++) HAL_IRDA_Transmit_IT() + (++) HAL_IRDA_Receive_IT() + (++) HAL_IRDA_IRQHandler() + + (#) Non Blocking mode functions with DMA are : + (++) HAL_IRDA_Transmit_DMA() + (++) HAL_IRDA_Receive_DMA() + (++) HAL_IRDA_DMAPause() + (++) HAL_IRDA_DMAResume() + (++) HAL_IRDA_DMAStop() + + (#) A set of Transfer Complete Callbacks are provided in Non Blocking mode: + (++) HAL_IRDA_TxHalfCpltCallback() + (++) HAL_IRDA_TxCpltCallback() + (++) HAL_IRDA_RxHalfCpltCallback() + (++) HAL_IRDA_RxCpltCallback() + (++) HAL_IRDA_ErrorCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_IRDA_Abort() + (+) HAL_IRDA_AbortTransmit() + (+) HAL_IRDA_AbortReceive() + (+) HAL_IRDA_Abort_IT() + (+) HAL_IRDA_AbortTransmit_IT() + (+) HAL_IRDA_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_IRDA_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_IRDA_AbortCpltCallback() + (+) HAL_IRDA_AbortTransmitCpltCallback() + (+) HAL_IRDA_AbortReceiveCpltCallback() + + (#) 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_IRDA_ErrorCallback() user callback is executed. Transfer is kept ongoing on IRDA 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_IRDA_ErrorCallback() user callback is executed. + +@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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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 Specify timeout value. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + const uint16_t *tmp; + uint32_t tickstart = 0U; + + /* Check that a Tx process is not already ongoing */ + if (hirda->gState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->gState = HAL_IRDA_STATE_BUSY_TX; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hirda->TxXferSize = Size; + hirda->TxXferCount = Size; + while (hirda->TxXferCount > 0U) + { + hirda->TxXferCount--; + if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B) + { + if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + tmp = (const uint16_t *) pData; + hirda->Instance->DR = (*tmp & (uint16_t)0x01FF); + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + pData += 2U; + } + else + { + pData += 1U; + } + } + else + { + if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + hirda->Instance->DR = (*pData++ & (uint8_t)0xFF); + } + } + + if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive 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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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 Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint16_t *tmp; + uint32_t tickstart = 0U; + + /* Check that a Rx process is not already ongoing */ + if (hirda->RxState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->RxState = HAL_IRDA_STATE_BUSY_RX; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + hirda->RxXferSize = Size; + hirda->RxXferCount = Size; + + /* Check the remain data to be received */ + while (hirda->RxXferCount > 0U) + { + hirda->RxXferCount--; + + if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B) + { + if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + tmp = (uint16_t *) pData ; + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + *tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x01FF); + pData += 2U; + } + else + { + *tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x00FF); + pData += 1U; + } + } + else + { + if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + *pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x007F); + } + } + } + + /* At end of Rx process, restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send 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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if (hirda->gState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->pTxBuffPtr = pData; + hirda->TxXferSize = Size; + hirda->TxXferCount = Size; + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->gState = HAL_IRDA_STATE_BUSY_TX; + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + /* Enable the IRDA Transmit Data Register Empty Interrupt */ + SET_BIT(hirda->Instance->CR1, USART_CR1_TXEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive 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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if (hirda->RxState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->pRxBuffPtr = pData; + hirda->RxXferSize = Size; + hirda->RxXferCount = Size; + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->RxState = HAL_IRDA_STATE_BUSY_RX; + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + if (hirda->Init.Parity != IRDA_PARITY_NONE) + { + /* Enable the IRDA Parity Error and Data Register Not Empty Interrupts */ + SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); + } + else + { + /* Enable the IRDA Data Register Not Empty Interrupts */ + SET_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE); + } + + /* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */ + SET_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send 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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size) +{ + const uint32_t *tmp; + + /* Check that a Tx process is not already ongoing */ + if (hirda->gState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->pTxBuffPtr = pData; + hirda->TxXferSize = Size; + hirda->TxXferCount = Size; + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->gState = HAL_IRDA_STATE_BUSY_TX; + + /* Set the IRDA DMA transfer complete callback */ + hirda->hdmatx->XferCpltCallback = IRDA_DMATransmitCplt; + + /* Set the IRDA DMA half transfer complete callback */ + hirda->hdmatx->XferHalfCpltCallback = IRDA_DMATransmitHalfCplt; + + /* Set the DMA error callback */ + hirda->hdmatx->XferErrorCallback = IRDA_DMAError; + + /* Set the DMA abort callback */ + hirda->hdmatx->XferAbortCallback = NULL; + + /* Enable the IRDA transmit DMA stream */ + tmp = (const uint32_t *)&pData; + HAL_DMA_Start_IT(hirda->hdmatx, *(const uint32_t *)tmp, (uint32_t)&hirda->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_IRDA_CLEAR_FLAG(hirda, IRDA_FLAG_TC); + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(hirda->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 reflect the number + * of u16 available through pData. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA 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 IRDA parity is enabled (PCE = 1) the data received contain the parity bit. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size) +{ + uint32_t *tmp; + + /* Check that a Rx process is not already ongoing */ + if (hirda->RxState == HAL_IRDA_STATE_READY) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hirda); + + hirda->pRxBuffPtr = pData; + hirda->RxXferSize = Size; + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + hirda->RxState = HAL_IRDA_STATE_BUSY_RX; + + /* Set the IRDA DMA transfer complete callback */ + hirda->hdmarx->XferCpltCallback = IRDA_DMAReceiveCplt; + + /* Set the IRDA DMA half transfer complete callback */ + hirda->hdmarx->XferHalfCpltCallback = IRDA_DMAReceiveHalfCplt; + + /* Set the DMA error callback */ + hirda->hdmarx->XferErrorCallback = IRDA_DMAError; + + /* Set the DMA abort callback */ + hirda->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + tmp = (uint32_t *)&pData; + HAL_DMA_Start_IT(hirda->hdmarx, (uint32_t)&hirda->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_IRDA_CLEAR_OREFLAG(hirda); + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + if (hirda->Init.Parity != IRDA_PARITY_NONE) + { + /* Enable the IRDA Parity Error Interrupt */ + SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE); + } + + /* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */ + SET_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pauses the DMA Transfer. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda) +{ + uint32_t dmarequest = 0x00U; + + /* Process Locked */ + __HAL_LOCK(hirda); + + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT); + if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest) + { + /* Disable the IRDA DMA Tx request */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + } + + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR); + if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest) + { + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Disable the IRDA DMA Rx request */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + return HAL_OK; +} + +/** + * @brief Resumes the DMA Transfer. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda) +{ + /* Process Locked */ + __HAL_LOCK(hirda); + + if (hirda->gState == HAL_IRDA_STATE_BUSY_TX) + { + /* Enable the IRDA DMA Tx request */ + SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + } + + if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX) + { + /* Clear the Overrun flag before resuming the Rx transfer */ + __HAL_IRDA_CLEAR_OREFLAG(hirda); + + /* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */ + if (hirda->Init.Parity != IRDA_PARITY_NONE) + { + SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE); + } + SET_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Enable the IRDA DMA Rx request */ + SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + return HAL_OK; +} + +/** + * @brief Stops the DMA Transfer. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef *hirda) +{ + uint32_t dmarequest = 0x00U; + /* The Lock is not implemented on this API to allow the user application + to call the HAL IRDA API under callbacks HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback() + */ + + /* Stop IRDA DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT); + if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Abort the IRDA DMA Tx channel */ + if (hirda->hdmatx != NULL) + { + HAL_DMA_Abort(hirda->hdmatx); + } + IRDA_EndTxTransfer(hirda); + } + + /* Stop IRDA DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR); + if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel */ + if (hirda->hdmarx != NULL) + { + HAL_DMA_Abort(hirda->hdmarx); + } + IRDA_EndRxTransfer(hirda); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_IRDA_Abort(IRDA_HandleTypeDef *hirda) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Disable the IRDA DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */ + if (hirda->hdmatx != NULL) + { + /* Set the IRDA DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hirda->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hirda->hdmatx); + } + } + + /* Disable the IRDA DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */ + if (hirda->hdmarx != NULL) + { + /* Set the IRDA DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hirda->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hirda->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + hirda->TxXferCount = 0x00U; + hirda->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + + /* Restore hirda->RxState and hirda->gState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + hirda->gState = HAL_IRDA_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_IRDA_AbortTransmit(IRDA_HandleTypeDef *hirda) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the IRDA DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */ + if (hirda->hdmatx != NULL) + { + /* Set the IRDA DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hirda->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hirda->hdmatx); + } + } + + /* Reset Tx transfer counter */ + hirda->TxXferCount = 0x00U; + + /* Restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_IRDA_AbortReceive(IRDA_HandleTypeDef *hirda) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Disable the IRDA DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */ + if (hirda->hdmarx != NULL) + { + /* Set the IRDA DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hirda->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hirda->hdmarx); + } + } + + /* Reset Rx transfer counter */ + hirda->RxXferCount = 0x00U; + + /* Restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_IRDA_Abort_IT(IRDA_HandleTypeDef *hirda) +{ + uint32_t AbortCplt = 0x01U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to IRDA Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if (hirda->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if IRDA DMA Tx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT)) + { + hirda->hdmatx->XferAbortCallback = IRDA_DMATxAbortCallback; + } + else + { + hirda->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if (hirda->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if IRDA DMA Rx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + hirda->hdmarx->XferAbortCallback = IRDA_DMARxAbortCallback; + } + else + { + hirda->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the IRDA DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at IRDA level */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */ + if (hirda->hdmatx != NULL) + { + /* IRDA Tx DMA Abort callback has already been initialised : + will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK) + { + hirda->hdmatx->XferAbortCallback = NULL; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* Disable the IRDA DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */ + if (hirda->hdmarx != NULL) + { + /* IRDA Rx DMA Abort callback has already been initialised : + will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK) + { + hirda->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 */ + hirda->TxXferCount = 0x00U; + hirda->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + + /* Restore hirda->gState and hirda->RxState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + hirda->RxState = HAL_IRDA_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hirda->AbortCpltCallback(hirda); +#else + /* Call legacy weak Abort complete callback */ + HAL_IRDA_AbortCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable IRDA 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_IRDA_AbortTransmit_IT(IRDA_HandleTypeDef *hirda) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the IRDA DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */ + if (hirda->hdmatx != NULL) + { + /* Set the IRDA DMA Abort callback : + will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */ + hirda->hdmatx->XferAbortCallback = IRDA_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK) + { + /* Call Directly hirda->hdmatx->XferAbortCallback function in case of error */ + hirda->hdmatx->XferAbortCallback(hirda->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + hirda->TxXferCount = 0x00U; + + /* Restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hirda->AbortTransmitCpltCallback(hirda); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_IRDA_AbortTransmitCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + } + else + { + /* Reset Tx transfer counter */ + hirda->TxXferCount = 0x00U; + + /* Restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hirda->AbortTransmitCpltCallback(hirda); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_IRDA_AbortTransmitCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param hirda IRDA handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_IRDA_AbortReceive_IT(IRDA_HandleTypeDef *hirda) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Disable the IRDA DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */ + if (hirda->hdmarx != NULL) + { + /* Set the IRDA DMA Abort callback : + will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */ + hirda->hdmarx->XferAbortCallback = IRDA_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK) + { + /* Call Directly hirda->hdmarx->XferAbortCallback function in case of error */ + hirda->hdmarx->XferAbortCallback(hirda->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + hirda->RxXferCount = 0x00U; + + /* Restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hirda->AbortReceiveCpltCallback(hirda); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_IRDA_AbortReceiveCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + } + else + { + /* Reset Rx transfer counter */ + hirda->RxXferCount = 0x00U; + + /* Restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hirda->AbortReceiveCpltCallback(hirda); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_IRDA_AbortReceiveCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + + return HAL_OK; +} + +/** + * @brief This function handles IRDA interrupt request. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +void HAL_IRDA_IRQHandler(IRDA_HandleTypeDef *hirda) +{ + uint32_t isrflags = READ_REG(hirda->Instance->SR); + uint32_t cr1its = READ_REG(hirda->Instance->CR1); + uint32_t cr3its = READ_REG(hirda->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) + { + /* IRDA in mode Receiver -----------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + IRDA_Receive_IT(hirda); + return; + } + } + + /* If some errors occur */ + if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) + { + /* IRDA parity error interrupt occurred -------------------------------*/ + if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + hirda->ErrorCode |= HAL_IRDA_ERROR_PE; + } + + /* IRDA noise error interrupt occurred --------------------------------*/ + if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + hirda->ErrorCode |= HAL_IRDA_ERROR_NE; + } + + /* IRDA frame error interrupt occurred --------------------------------*/ + if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + hirda->ErrorCode |= HAL_IRDA_ERROR_FE; + } + + /* IRDA Over-Run interrupt occurred -----------------------------------*/ + if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET))) + { + hirda->ErrorCode |= HAL_IRDA_ERROR_ORE; + } + /* Call IRDA Error Call back function if need be -----------------------*/ + if (hirda->ErrorCode != HAL_IRDA_ERROR_NONE) + { + /* IRDA in mode Receiver ---------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + IRDA_Receive_IT(hirda); + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR); + if (((hirda->ErrorCode & HAL_IRDA_ERROR_ORE) != RESET) || dmarequest) + { + /* Blocking error : transfer is aborted + Set the IRDA state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + IRDA_EndRxTransfer(hirda); + + /* Disable the IRDA DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* Abort the IRDA DMA Rx channel */ + if (hirda->hdmarx != NULL) + { + /* Set the IRDA DMA Abort callback : + will lead to call HAL_IRDA_ErrorCallback() at end of DMA abort procedure */ + hirda->hdmarx->XferAbortCallback = IRDA_DMAAbortOnError; + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hirda->hdmarx->XferAbortCallback(hirda->hdmarx); + } + } + else + { +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hirda->ErrorCallback(hirda); +#else + /* Call legacy weak user error callback */ + HAL_IRDA_ErrorCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + } + else + { +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hirda->ErrorCallback(hirda); +#else + /* Call legacy weak user error callback */ + HAL_IRDA_ErrorCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hirda->ErrorCallback(hirda); +#else + /* Call legacy weak user error callback */ + HAL_IRDA_ErrorCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + } + } + return; + } /* End if some error occurs */ + + /* IRDA in mode Transmitter ------------------------------------------------*/ + if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) + { + IRDA_Transmit_IT(hirda); + return; + } + + /* IRDA in mode Transmitter end --------------------------------------------*/ + if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + IRDA_EndTransmit_IT(hirda); + return; + } +} + +/** + * @brief Tx Transfer complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_TxCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_TxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_TxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Transfer complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_RxCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_RxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Half Transfer complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_RxHalfCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief IRDA error callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_ErrorCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief IRDA Abort Complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_AbortCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief IRDA Abort Transmit Complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_AbortTransmitCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief IRDA Abort Receive Complete callback. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +__weak void HAL_IRDA_AbortReceiveCpltCallback(IRDA_HandleTypeDef *hirda) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hirda); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_IRDA_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup IRDA_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief IRDA State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of IrDA + communication process and also return Peripheral Errors occurred during communication process + (+) HAL_IRDA_GetState() API can be helpful to check in run-time the state of the IrDA peripheral. + (+) HAL_IRDA_GetError() check in run-time errors that could be occurred during communication. + +@endverbatim + * @{ + */ + +/** + * @brief Return the IRDA state. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA. + * @retval HAL state + */ +HAL_IRDA_StateTypeDef HAL_IRDA_GetState(const IRDA_HandleTypeDef *hirda) +{ + uint32_t temp1 = 0x00U, temp2 = 0x00U; + temp1 = hirda->gState; + temp2 = hirda->RxState; + + return (HAL_IRDA_StateTypeDef)(temp1 | temp2); +} + +/** + * @brief Return the IRDA error code + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA. + * @retval IRDA Error Code + */ +uint32_t HAL_IRDA_GetError(const IRDA_HandleTypeDef *hirda) +{ + return hirda->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup IRDA_Private_Functions IRDA Private Functions + * @{ + */ + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) +/** + * @brief Initialize the callbacks to their default values. + * @param hirda IRDA handle. + * @retval none + */ +void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda) +{ + /* Init the IRDA Callback settings */ + hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */ + hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + +} +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + +/** + * @brief DMA IRDA transmit process complete callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA. + * @retval None + */ +static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* DMA Normal mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + hirda->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by resetting the DMAT bit + in the IRDA CR3 register */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT); + + /* Enable the IRDA Transmit Complete Interrupt */ + SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE); + } + /* DMA Circular mode */ + else + { +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Tx complete callback */ + hirda->TxCpltCallback(hirda); +#else + /* Call legacy weak Tx complete callback */ + HAL_IRDA_TxCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + } +} + +/** + * @brief DMA IRDA receive process half complete callback + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA. + * @retval None + */ +static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Tx Half complete callback */ + hirda->TxHalfCpltCallback(hirda); +#else + /* Call legacy weak Tx complete callback */ + HAL_IRDA_TxHalfCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA receive process complete callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA. + * @retval None + */ +static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* DMA Normal mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + hirda->RxXferCount = 0U; + + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by resetting the DMAR bit + in the IRDA CR3 register */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + } + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Rx complete callback */ + hirda->RxCpltCallback(hirda); +#else + /* Call legacy weak Rx complete callback */ + HAL_IRDA_RxCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA IRDA receive process half complete callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA. + * @retval None + */ +static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /*Call registered Rx Half complete callback*/ + hirda->RxHalfCpltCallback(hirda); +#else + /* Call legacy weak Rx Half complete callback */ + HAL_IRDA_RxHalfCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA communication error callback. + * @param hdma Pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA. + * @retval None + */ +static void IRDA_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t dmarequest = 0x00U; + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Stop IRDA DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT); + if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest) + { + hirda->TxXferCount = 0U; + IRDA_EndTxTransfer(hirda); + } + + /* Stop IRDA DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR); + if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest) + { + hirda->RxXferCount = 0U; + IRDA_EndRxTransfer(hirda); + } + + hirda->ErrorCode |= HAL_IRDA_ERROR_DMA; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hirda->ErrorCallback(hirda); +#else + /* Call legacy weak user error callback */ + HAL_IRDA_ErrorCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief This function handles IRDA Communication Timeout. It waits + * until a flag is no longer in the specified status. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA. + * @param Flag specifies the IRDA 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 IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while ((__HAL_IRDA_GET_FLAG(hirda, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + hirda->gState = HAL_IRDA_STATE_READY; + hirda->RxState = HAL_IRDA_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hirda); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief End ongoing Tx transfer on IRDA peripheral (following error detection or Transmit completion). + * @param hirda IRDA handle. + * @retval None + */ +static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* At end of Tx process, restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; +} + +/** + * @brief End ongoing Rx transfer on IRDA peripheral (following error detection or Reception completion). + * @param hirda IRDA handle. + * @retval None + */ +static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; +} + +/** + * @brief DMA IRDA communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + hirda->RxXferCount = 0x00U; + hirda->TxXferCount = 0x00U; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hirda->ErrorCallback(hirda); +#else + /* Call legacy weak user error callback */ + HAL_IRDA_ErrorCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA 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 DMA handle. + * @retval None + */ +static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + hirda->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (hirda->hdmarx != NULL) + { + if (hirda->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + hirda->TxXferCount = 0x00U; + hirda->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + + /* Restore hirda->gState and hirda->RxState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + hirda->RxState = HAL_IRDA_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hirda->AbortCpltCallback(hirda); +#else + /* Call legacy weak Abort complete callback */ + HAL_IRDA_AbortCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA 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 DMA handle. + * @retval None + */ +static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + hirda->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (hirda->hdmatx != NULL) + { + if (hirda->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + hirda->TxXferCount = 0x00U; + hirda->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hirda->ErrorCode = HAL_IRDA_ERROR_NONE; + + /* Restore hirda->gState and hirda->RxState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + hirda->RxState = HAL_IRDA_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hirda->AbortCpltCallback(hirda); +#else + /* Call legacy weak Abort complete callback */ + HAL_IRDA_AbortCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA Tx communication abort callback, when initiated by user by a call to + * HAL_IRDA_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 DMA handle. + * @retval None + */ +static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + hirda->TxXferCount = 0x00U; + + /* Restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hirda->AbortTransmitCpltCallback(hirda); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_IRDA_AbortTransmitCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief DMA IRDA Rx communication abort callback, when initiated by user by a call to + * HAL_IRDA_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 DMA handle. + * @retval None + */ +static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + hirda->RxXferCount = 0x00U; + + /* Restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hirda->AbortReceiveCpltCallback(hirda); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_IRDA_AbortReceiveCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ +} + +/** + * @brief Send an amount of data in non blocking mode. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda) +{ + const uint16_t *tmp; + + /* Check that a Tx process is ongoing */ + if (hirda->gState == HAL_IRDA_STATE_BUSY_TX) + { + if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B) + { + tmp = (const uint16_t *) hirda->pTxBuffPtr; + hirda->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF); + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + hirda->pTxBuffPtr += 2U; + } + else + { + hirda->pTxBuffPtr += 1U; + } + } + else + { + hirda->Instance->DR = (uint8_t)(*hirda->pTxBuffPtr++ & (uint8_t)0x00FF); + } + + if (--hirda->TxXferCount == 0U) + { + /* Disable the IRDA Transmit Data Register Empty Interrupt */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TXEIE); + + /* Enable the IRDA Transmit Complete Interrupt */ + SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Wraps up transmission in non blocking mode. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda) +{ + /* Disable the IRDA Transmit Complete Interrupt */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TCIE); + + /* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Tx process is ended, restore hirda->gState to Ready */ + hirda->gState = HAL_IRDA_STATE_READY; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Tx complete callback */ + hirda->TxCpltCallback(hirda); +#else + /* Call legacy weak Tx complete callback */ + HAL_IRDA_TxCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */ + + return HAL_OK; +} + +/** + * @brief Receives an amount of data in non blocking mode. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval HAL status + */ +static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda) +{ + uint16_t *tmp; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(hirda->Instance->DR); + if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B) + { + tmp = (uint16_t *) hirda->pRxBuffPtr; + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + *tmp = (uint16_t)(uhdata & (uint16_t)0x01FF); + hirda->pRxBuffPtr += 2U; + } + else + { + *tmp = (uint16_t)(uhdata & (uint16_t)0x00FF); + hirda->pRxBuffPtr += 1U; + } + } + else + { + if (hirda->Init.Parity == IRDA_PARITY_NONE) + { + *hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x00FF); + } + else + { + *hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x007F); + } + } + + if (--hirda->RxXferCount == 0U) + { + /* Disable the IRDA Data Register not empty Interrupt */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE); + + /* Disable the IRDA Parity Error Interrupt */ + CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE); + + /* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore hirda->RxState to Ready */ + hirda->RxState = HAL_IRDA_STATE_READY; + +#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1) + /* Call registered Rx complete callback */ + hirda->RxCpltCallback(hirda); +#else + /* Call legacy weak Rx complete callback */ + HAL_IRDA_RxCpltCallback(hirda); +#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */ + + return HAL_OK; + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures the IRDA peripheral. + * @param hirda Pointer to a IRDA_HandleTypeDef structure that contains + * the configuration information for the specified IRDA module. + * @retval None + */ +static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda) +{ + uint32_t pclk; + + /* Check the parameters */ + assert_param(IS_IRDA_INSTANCE(hirda->Instance)); + assert_param(IS_IRDA_BAUDRATE(hirda->Init.BaudRate)); + assert_param(IS_IRDA_WORD_LENGTH(hirda->Init.WordLength)); + assert_param(IS_IRDA_PARITY(hirda->Init.Parity)); + assert_param(IS_IRDA_MODE(hirda->Init.Mode)); + assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode)); + + /*-------------------------- USART CR2 Configuration ------------------------*/ + /* Clear STOP[13:12] bits */ + CLEAR_BIT(hirda->Instance->CR2, USART_CR2_STOP); + + /*-------------------------- USART CR1 Configuration -----------------------*/ + /* Clear M, PCE, PS, TE and RE bits */ + CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE)); + + /* Configure the USART Word Length, Parity and mode: + Set the M bits according to hirda->Init.WordLength value + Set PCE and PS bits according to hirda->Init.Parity value + Set TE and RE bits according to hirda->Init.Mode value */ + /* Write to USART CR1 */ + SET_BIT(hirda->Instance->CR1, (hirda->Init.WordLength | hirda->Init.Parity | hirda->Init.Mode)); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Clear CTSE and RTSE bits */ + CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE)); + + /*-------------------------- USART BRR Configuration -----------------------*/ +#if defined(USART6) && defined(UART9) && defined(UART10) + if ((hirda->Instance == USART1) || (hirda->Instance == USART6) || (hirda->Instance == UART9) || (hirda->Instance == UART10)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate)); + } +#elif defined(USART6) + if((hirda->Instance == USART1) || (hirda->Instance == USART6)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate)); + } +#else + if(hirda->Instance == USART1) + { + pclk = HAL_RCC_GetPCLK2Freq(); + SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate)); + } +#endif /* USART6 */ + else + { + pclk = HAL_RCC_GetPCLK1Freq(); + SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate)); + } +} + +/** + * @} + */ + +#endif /* HAL_IRDA_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c new file mode 100644 index 0000000..c01eb29 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c @@ -0,0 +1,262 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_iwdg.c + * @author MCD Application Team + * @brief IWDG HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Independent Watchdog (IWDG) peripheral: + * + Initialization and Start functions + * + IO operation 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 + ============================================================================== + ##### IWDG Generic features ##### + ============================================================================== + [..] + (+) The IWDG can be started by either software or hardware (configurable + through option byte). + + (+) The IWDG is clocked by the Low-Speed Internal clock (LSI) and thus stays + active even if the main clock fails. + + (+) Once the IWDG is started, the LSI is forced ON and both cannot be + disabled. The counter starts counting down from the reset value (0xFFF). + When it reaches the end of count value (0x000) a reset signal is + generated (IWDG reset). + + (+) Whenever the key value 0x0000 AAAA is written in the IWDG_KR register, + the IWDG_RLR value is reloaded into the counter and the watchdog reset + is prevented. + + (+) The IWDG is implemented in the VDD voltage domain that is still functional + in STOP and STANDBY mode (IWDG reset can wake up the CPU from STANDBY). + IWDGRST flag in RCC_CSR register can be used to inform when an IWDG + reset occurs. + + (+) Debug mode: When the microcontroller enters debug mode (core halted), + the IWDG counter either continues to work normally or stops, depending + on DBG_IWDG_STOP configuration bit in DBG module, accessible through + __HAL_DBGMCU_FREEZE_IWDG() and __HAL_DBGMCU_UNFREEZE_IWDG() macros. + + [..] Min-max timeout value @32KHz (LSI): ~125us / ~32.7s + The IWDG timeout may vary due to LSI clock frequency dispersion. + STM32F4xx devices provide the capability to measure the LSI clock + frequency (LSI clock is internally connected to TIM5 CH4 input capture). + The measured value can be used to have an IWDG timeout with an + acceptable accuracy. + + [..] Default timeout value (necessary for IWDG_SR status register update): + Constant LSI_VALUE is defined based on the nominal LSI clock frequency. + This frequency being subject to variations as mentioned above, the + default timeout value (defined through constant HAL_IWDG_DEFAULT_TIMEOUT + below) may become too short or too long. + In such cases, this default timeout value can be tuned by redefining + the constant LSI_VALUE at user-application level (based, for instance, + on the measured LSI clock frequency as explained above). + + ##### How to use this driver ##### + ============================================================================== + [..] + (#) Use IWDG using HAL_IWDG_Init() function to : + (++) Enable instance by writing Start keyword in IWDG_KEY register. LSI + clock is forced ON and IWDG counter starts counting down. + (++) Enable write access to configuration registers: + IWDG_PR and IWDG_RLR. + (++) Configure the IWDG prescaler and counter reload value. This reload + value will be loaded in the IWDG counter each time the watchdog is + reloaded, then the IWDG will start counting down from this value. + (++) Wait for status flags to be reset. + + (#) Then the application program must refresh the IWDG counter at regular + intervals during normal operation to prevent an MCU reset, using + HAL_IWDG_Refresh() function. + + *** IWDG HAL driver macros list *** + ==================================== + [..] + Below the list of most used macros in IWDG HAL driver: + (+) __HAL_IWDG_START: Enable the IWDG peripheral + (+) __HAL_IWDG_RELOAD_COUNTER: Reloads IWDG counter with value defined in + the reload register + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_IWDG_MODULE_ENABLED +/** @addtogroup IWDG + * @brief IWDG HAL module driver. + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup IWDG_Private_Defines IWDG Private Defines + * @{ + */ +/* Status register needs up to 5 LSI clock periods divided by the clock + prescaler to be updated. The number of LSI clock periods is upper-rounded to + 6 for the timeout value calculation. + The timeout value is calculated using the highest prescaler (256) and + the LSI_VALUE constant. The value of this constant can be changed by the user + to take into account possible LSI clock period variations. + The timeout value is multiplied by 1000 to be converted in milliseconds. + LSI startup time is also considered here by adding LSI_STARTUP_TIME + converted in milliseconds. */ +#define HAL_IWDG_DEFAULT_TIMEOUT (((6UL * 256UL * 1000UL) / LSI_VALUE) + ((LSI_STARTUP_TIME / 1000UL) + 1UL)) +#define IWDG_KERNEL_UPDATE_FLAGS (IWDG_SR_RVU | IWDG_SR_PVU) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup IWDG_Exported_Functions + * @{ + */ + +/** @addtogroup IWDG_Exported_Functions_Group1 + * @brief Initialization and Start functions. + * +@verbatim + =============================================================================== + ##### Initialization and Start functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the IWDG according to the specified parameters in the + IWDG_InitTypeDef of associated handle. + (+) Once initialization is performed in HAL_IWDG_Init function, Watchdog + is reloaded in order to exit function with correct time base. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the IWDG according to the specified parameters in the + * IWDG_InitTypeDef and start watchdog. Before exiting function, + * watchdog is refreshed in order to have correct time base. + * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains + * the configuration information for the specified IWDG module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg) +{ + uint32_t tickstart; + + /* Check the IWDG handle allocation */ + if (hiwdg == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance)); + assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler)); + assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload)); + + /* Enable IWDG. LSI is turned on automatically */ + __HAL_IWDG_START(hiwdg); + + /* Enable write access to IWDG_PR and IWDG_RLR registers by writing + 0x5555 in KR */ + IWDG_ENABLE_WRITE_ACCESS(hiwdg); + + /* Write to IWDG registers the Prescaler & Reload values to work with */ + hiwdg->Instance->PR = hiwdg->Init.Prescaler; + hiwdg->Instance->RLR = hiwdg->Init.Reload; + + /* Check pending flag, if previous update not done, return timeout */ + tickstart = HAL_GetTick(); + + /* Wait for register to be updated */ + while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u) + { + if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT) + { + if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u) + { + return HAL_TIMEOUT; + } + } + } + + /* Reload IWDG counter with value defined in the reload register */ + __HAL_IWDG_RELOAD_COUNTER(hiwdg); + + /* Return function status */ + return HAL_OK; +} + + +/** + * @} + */ + + +/** @addtogroup IWDG_Exported_Functions_Group2 + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Refresh the IWDG. + +@endverbatim + * @{ + */ + +/** + * @brief Refresh the IWDG. + * @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains + * the configuration information for the specified IWDG module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg) +{ + /* Reload IWDG counter with value defined in the reload register */ + __HAL_IWDG_RELOAD_COUNTER(hiwdg); + + /* Return function status */ + return HAL_OK; +} + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_IWDG_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c new file mode 100644 index 0000000..e302d59 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_lptim.c @@ -0,0 +1,2484 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_lptim.c + * @author MCD Application Team + * @brief LPTIM HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Low Power Timer (LPTIM) peripheral: + * + Initialization and de-initialization functions. + * + Start/Stop operation functions in polling mode. + * + Start/Stop operation functions in interrupt mode. + * + Reading operation functions. + * + Peripheral State 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 LPTIM HAL driver can be used as follows: + + (#)Initialize the LPTIM low level resources by implementing the + HAL_LPTIM_MspInit(): + (++) Enable the LPTIM interface clock using __HAL_RCC_LPTIMx_CLK_ENABLE(). + (++) In case of using interrupts (e.g. HAL_LPTIM_PWM_Start_IT()): + (+++) Configure the LPTIM interrupt priority using HAL_NVIC_SetPriority(). + (+++) Enable the LPTIM IRQ handler using HAL_NVIC_EnableIRQ(). + (+++) In LPTIM IRQ handler, call HAL_LPTIM_IRQHandler(). + + (#)Initialize the LPTIM HAL using HAL_LPTIM_Init(). This function + configures mainly: + (++) The instance: LPTIM1. + (++) Clock: the counter clock. + (+++) Source : it can be either the ULPTIM input (IN1) or one of + the internal clock; (APB, LSE or LSI). + (+++) Prescaler: select the clock divider. + (++) UltraLowPowerClock : To be used only if the ULPTIM is selected + as counter clock source. + (+++) Polarity: polarity of the active edge for the counter unit + if the ULPTIM input is selected. + (+++) SampleTime: clock sampling time to configure the clock glitch + filter. + (++) Trigger: How the counter start. + (+++) Source: trigger can be software or one of the hardware triggers. + (+++) ActiveEdge : only for hardware trigger. + (+++) SampleTime : trigger sampling time to configure the trigger + glitch filter. + (++) OutputPolarity : 2 opposite polarities are possible. + (++) UpdateMode: specifies whether the update of the autoreload and + the compare values is done immediately or after the end of current + period. + + (#)Six modes are available: + + (++) PWM Mode: To generate a PWM signal with specified period and pulse, + call HAL_LPTIM_PWM_Start() or HAL_LPTIM_PWM_Start_IT() for interruption + mode. + + (++) One Pulse Mode: To generate pulse with specified width in response + to a stimulus, call HAL_LPTIM_OnePulse_Start() or + HAL_LPTIM_OnePulse_Start_IT() for interruption mode. + + (++) Set once Mode: In this mode, the output changes the level (from + low level to high level if the output polarity is configured high, else + the opposite) when a compare match occurs. To start this mode, call + HAL_LPTIM_SetOnce_Start() or HAL_LPTIM_SetOnce_Start_IT() for + interruption mode. + + (++) Encoder Mode: To use the encoder interface call + HAL_LPTIM_Encoder_Start() or HAL_LPTIM_Encoder_Start_IT() for + interruption mode. Only available for LPTIM1 instance. + + (++) Time out Mode: an active edge on one selected trigger input rests + the counter. The first trigger event will start the timer, any + successive trigger event will reset the counter and the timer will + restart. To start this mode call HAL_LPTIM_TimeOut_Start_IT() or + HAL_LPTIM_TimeOut_Start_IT() for interruption mode. + + (++) Counter Mode: counter can be used to count external events on + the LPTIM Input1 or it can be used to count internal clock cycles. + To start this mode, call HAL_LPTIM_Counter_Start() or + HAL_LPTIM_Counter_Start_IT() for interruption mode. + + + (#) User can stop any process by calling the corresponding API: + HAL_LPTIM_Xxx_Stop() or HAL_LPTIM_Xxx_Stop_IT() if the process is + already started in interruption mode. + + (#) De-initialize the LPTIM peripheral using HAL_LPTIM_DeInit(). + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_LPTIM_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + [..] + Use Function HAL_LPTIM_RegisterCallback() to register a callback. + HAL_LPTIM_RegisterCallback() takes as parameters the HAL peripheral handle, + the Callback ID and a pointer to the user callback function. + [..] + Use function HAL_LPTIM_UnRegisterCallback() to reset a callback to the + default weak function. + HAL_LPTIM_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + [..] + These functions allow to register/unregister following callbacks: + + (+) MspInitCallback : LPTIM Base Msp Init Callback. + (+) MspDeInitCallback : LPTIM Base Msp DeInit Callback. + (+) CompareMatchCallback : Compare match Callback. + (+) AutoReloadMatchCallback : Auto-reload match Callback. + (+) TriggerCallback : External trigger event detection Callback. + (+) CompareWriteCallback : Compare register write complete Callback. + (+) AutoReloadWriteCallback : Auto-reload register write complete Callback. + (+) DirectionUpCallback : Up-counting direction change Callback. + (+) DirectionDownCallback : Down-counting direction change Callback. + + [..] + By default, after the Init and when the state is HAL_LPTIM_STATE_RESET + all interrupt callbacks are set to the corresponding weak functions: + examples HAL_LPTIM_TriggerCallback(), HAL_LPTIM_CompareMatchCallback(). + + [..] + Exception done for MspInit and MspDeInit functions that are reset to the legacy weak + functionalities in the Init/DeInit only when these callbacks are null + (not registered beforehand). If not, MspInit or MspDeInit are not null, the Init/DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + [..] + Callbacks can be registered/unregistered in HAL_LPTIM_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_LPTIM_STATE_READY or HAL_LPTIM_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_LPTIM_RegisterCallback() before calling DeInit or Init function. + + [..] + When The compilation define USE_HAL_LPTIM_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup LPTIM LPTIM + * @brief LPTIM HAL module driver. + * @{ + */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + +#if defined (LPTIM1) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup LPTIM_Private_Constants + * @{ + */ +#define TIMEOUT 1000UL /* Timeout is 1s */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +static void LPTIM_ResetCallback(LPTIM_HandleTypeDef *lptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ +static HAL_StatusTypeDef LPTIM_WaitForFlag(LPTIM_HandleTypeDef *hlptim, uint32_t flag); + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup LPTIM_Exported_Functions LPTIM Exported Functions + * @{ + */ + +/** @defgroup LPTIM_Exported_Functions_Group1 Initialization/de-initialization functions + * @brief Initialization and Configuration functions. + * +@verbatim + ============================================================================== + ##### Initialization and de-initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Initialize the LPTIM according to the specified parameters in the + LPTIM_InitTypeDef and initialize the associated handle. + (+) DeInitialize the LPTIM peripheral. + (+) Initialize the LPTIM MSP. + (+) DeInitialize the LPTIM MSP. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the LPTIM according to the specified parameters in the + * LPTIM_InitTypeDef and initialize the associated handle. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Init(LPTIM_HandleTypeDef *hlptim) +{ + uint32_t tmpcfgr; + + /* Check the LPTIM handle allocation */ + if (hlptim == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + assert_param(IS_LPTIM_CLOCK_SOURCE(hlptim->Init.Clock.Source)); + assert_param(IS_LPTIM_CLOCK_PRESCALER(hlptim->Init.Clock.Prescaler)); + if ((hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM) + || (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL)) + { + assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity)); + assert_param(IS_LPTIM_CLOCK_SAMPLE_TIME(hlptim->Init.UltraLowPowerClock.SampleTime)); + } + assert_param(IS_LPTIM_TRG_SOURCE(hlptim->Init.Trigger.Source)); + if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE) + { + assert_param(IS_LPTIM_EXT_TRG_POLARITY(hlptim->Init.Trigger.ActiveEdge)); + assert_param(IS_LPTIM_TRIG_SAMPLE_TIME(hlptim->Init.Trigger.SampleTime)); + } + assert_param(IS_LPTIM_OUTPUT_POLARITY(hlptim->Init.OutputPolarity)); + assert_param(IS_LPTIM_UPDATE_MODE(hlptim->Init.UpdateMode)); + assert_param(IS_LPTIM_COUNTER_SOURCE(hlptim->Init.CounterSource)); + + if (hlptim->State == HAL_LPTIM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hlptim->Lock = HAL_UNLOCKED; + +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + /* Reset interrupt callbacks to legacy weak callbacks */ + LPTIM_ResetCallback(hlptim); + + if (hlptim->MspInitCallback == NULL) + { + hlptim->MspInitCallback = HAL_LPTIM_MspInit; + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + hlptim->MspInitCallback(hlptim); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_LPTIM_MspInit(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Get the LPTIMx CFGR value */ + tmpcfgr = hlptim->Instance->CFGR; + + if ((hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM) + || (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL)) + { + tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_CKPOL | LPTIM_CFGR_CKFLT)); + } + if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE) + { + tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_TRGFLT | LPTIM_CFGR_TRIGSEL)); + } + + /* Clear CKSEL, PRESC, TRIGEN, TRGFLT, WAVPOL, PRELOAD & COUNTMODE bits */ + tmpcfgr &= (uint32_t)(~(LPTIM_CFGR_CKSEL | LPTIM_CFGR_TRIGEN | LPTIM_CFGR_PRELOAD | + LPTIM_CFGR_WAVPOL | LPTIM_CFGR_PRESC | LPTIM_CFGR_COUNTMODE)); + + /* Set initialization parameters */ + tmpcfgr |= (hlptim->Init.Clock.Source | + hlptim->Init.Clock.Prescaler | + hlptim->Init.OutputPolarity | + hlptim->Init.UpdateMode | + hlptim->Init.CounterSource); + + /* Glitch filters for internal triggers and external inputs are configured + * only if an internal clock source is provided to the LPTIM + */ + if (hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC) + { + tmpcfgr |= (hlptim->Init.Trigger.SampleTime | + hlptim->Init.UltraLowPowerClock.SampleTime); + } + + /* Configure LPTIM external clock polarity and digital filter */ + if ((hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_ULPTIM) + || (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL)) + { + tmpcfgr |= (hlptim->Init.UltraLowPowerClock.Polarity | + hlptim->Init.UltraLowPowerClock.SampleTime); + } + + /* Configure LPTIM external trigger */ + if (hlptim->Init.Trigger.Source != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Enable External trigger and set the trigger source */ + tmpcfgr |= (hlptim->Init.Trigger.Source | + hlptim->Init.Trigger.ActiveEdge | + hlptim->Init.Trigger.SampleTime); + } + + /* Write to LPTIMx CFGR */ + hlptim->Instance->CFGR = tmpcfgr; + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief DeInitialize the LPTIM peripheral. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_DeInit(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the LPTIM handle allocation */ + if (hlptim == NULL) + { + return HAL_ERROR; + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the LPTIM Peripheral Clock */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + if (hlptim->MspDeInitCallback == NULL) + { + hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit; + } + + /* DeInit the low level hardware: CLOCK, NVIC.*/ + hlptim->MspDeInitCallback(hlptim); +#else + /* DeInit the low level hardware: CLOCK, NVIC.*/ + HAL_LPTIM_MspDeInit(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hlptim); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initialize the LPTIM MSP. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize LPTIM MSP. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_MspDeInit(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup LPTIM_Exported_Functions_Group2 LPTIM Start-Stop operation functions + * @brief Start-Stop operation functions. + * +@verbatim + ============================================================================== + ##### LPTIM Start Stop operation functions ##### + ============================================================================== + [..] This section provides functions allowing to: + (+) Start the PWM mode. + (+) Stop the PWM mode. + (+) Start the One pulse mode. + (+) Stop the One pulse mode. + (+) Start the Set once mode. + (+) Stop the Set once mode. + (+) Start the Encoder mode. + (+) Stop the Encoder mode. + (+) Start the Timeout mode. + (+) Stop the Timeout mode. + (+) Start the Counter mode. + (+) Stop the Counter mode. + + +@endverbatim + * @{ + */ + +/** + * @brief Start the LPTIM PWM generation. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Reset WAVE bit to set PWM mode */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM PWM generation. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the LPTIM PWM generation in interrupt mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Reset WAVE bit to set PWM mode */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable Autoreload write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Enable Compare write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Enable Autoreload match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Enable Compare match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then enable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Enable external trigger interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM PWM generation in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_PWM_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable Autoreload write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Disable Compare write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Disable Autoreload match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Disable Compare match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then disable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Disable external trigger interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the LPTIM One pulse generation. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Reset WAVE bit to set one pulse mode */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in single (one shot) mode */ + __HAL_LPTIM_START_SINGLE(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM One pulse generation. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the LPTIM One pulse generation in interrupt mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Reset WAVE bit to set one pulse mode */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable Autoreload write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Enable Compare write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Enable Autoreload match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Enable Compare match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then enable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Enable external trigger interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in single (one shot) mode */ + __HAL_LPTIM_START_SINGLE(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM One pulse generation in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_OnePulse_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable Autoreload write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Disable Compare write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Disable Autoreload match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Disable Compare match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then disable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Disable external trigger interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the LPTIM in Set once mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Set WAVE bit to enable the set once mode */ + hlptim->Instance->CFGR |= LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in single (one shot) mode */ + __HAL_LPTIM_START_SINGLE(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM Set once mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the LPTIM Set once mode in interrupt mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @param Pulse Specifies the compare value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Pulse) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Pulse)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Set WAVE bit to enable the set once mode */ + hlptim->Instance->CFGR |= LPTIM_CFGR_WAVE; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the pulse value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Pulse); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable Autoreload write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Enable Compare write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Enable Autoreload match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Enable Compare match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then enable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Enable external trigger interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in single (one shot) mode */ + __HAL_LPTIM_START_SINGLE(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the LPTIM Set once mode in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_SetOnce_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable Autoreload write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Disable Compare write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPOK); + + /* Disable Autoreload match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Disable Compare match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* If external trigger source is used, then disable external trigger interrupt */ + if ((hlptim->Init.Trigger.Source) != LPTIM_TRIGSOURCE_SOFTWARE) + { + /* Disable external trigger interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_EXTTRIG); + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Encoder interface. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period) +{ + uint32_t tmpcfgr; + + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC); + assert_param(hlptim->Init.Clock.Prescaler == LPTIM_PRESCALER_DIV1); + assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Get the LPTIMx CFGR value */ + tmpcfgr = hlptim->Instance->CFGR; + + /* Clear CKPOL bits */ + tmpcfgr &= (uint32_t)(~LPTIM_CFGR_CKPOL); + + /* Set Input polarity */ + tmpcfgr |= hlptim->Init.UltraLowPowerClock.Polarity; + + /* Write to LPTIMx CFGR */ + hlptim->Instance->CFGR = tmpcfgr; + + /* Set ENC bit to enable the encoder interface */ + hlptim->Instance->CFGR |= LPTIM_CFGR_ENC; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Encoder interface. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Reset ENC bit to disable the encoder interface */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_ENC; + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Encoder interface in interrupt mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period) +{ + uint32_t tmpcfgr; + + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(hlptim->Init.Clock.Source == LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC); + assert_param(hlptim->Init.Clock.Prescaler == LPTIM_PRESCALER_DIV1); + assert_param(IS_LPTIM_CLOCK_POLARITY(hlptim->Init.UltraLowPowerClock.Polarity)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Configure edge sensitivity for encoder mode */ + /* Get the LPTIMx CFGR value */ + tmpcfgr = hlptim->Instance->CFGR; + + /* Clear CKPOL bits */ + tmpcfgr &= (uint32_t)(~LPTIM_CFGR_CKPOL); + + /* Set Input polarity */ + tmpcfgr |= hlptim->Init.UltraLowPowerClock.Polarity; + + /* Write to LPTIMx CFGR */ + hlptim->Instance->CFGR = tmpcfgr; + + /* Set ENC bit to enable the encoder interface */ + hlptim->Instance->CFGR |= LPTIM_CFGR_ENC; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable "switch to down direction" interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_DOWN); + + /* Enable "switch to up direction" interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_UP); + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Encoder interface in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Encoder_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Reset ENC bit to disable the encoder interface */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_ENC; + + /* Disable "switch to down direction" interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_DOWN); + + /* Disable "switch to up direction" interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_UP); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Timeout function. + * @note The first trigger event will start the timer, any successive + * trigger event will reset the counter and the timer restarts. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Timeout Specifies the TimeOut value to reset the counter. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Timeout)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Set TIMOUT bit to enable the timeout function */ + hlptim->Instance->CFGR |= LPTIM_CFGR_TIMOUT; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the Timeout value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Timeout); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Timeout function. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Reset TIMOUT bit to enable the timeout function */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_TIMOUT; + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Timeout function in interrupt mode. + * @note The first trigger event will start the timer, any successive + * trigger event will reset the counter and the timer restarts. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @param Timeout Specifies the TimeOut value to reset the counter. + * This parameter must be a value between 0x0000 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period, uint32_t Timeout) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + assert_param(IS_LPTIM_PULSE(Timeout)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Enable EXTI Line interrupt on the LPTIM Wake-up Timer */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_IT(); +#if defined(EXTI_IMR_MR23) + /* Enable rising edge trigger on the LPTIM Wake-up Timer Exti line */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); +#endif /* EXTI_IMR_MR23 */ + + /* Set TIMOUT bit to enable the timeout function */ + hlptim->Instance->CFGR |= LPTIM_CFGR_TIMOUT; + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Load the Timeout value in the compare register */ + __HAL_LPTIM_COMPARE_SET(hlptim, Timeout); + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable Compare match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Timeout function in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_TimeOut_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + +#if defined(EXTI_IMR_MR23) + /* Disable rising edge trigger on the LPTIM Wake-up Timer Exti line */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE(); +#endif /* EXTI_IMR_MR23 */ + + /* Disable EXTI Line interrupt on the LPTIM Wake-up Timer */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_IT(); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Reset TIMOUT bit to enable the timeout function */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_TIMOUT; + + /* Disable Compare match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_CMPM); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Counter mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Start(LPTIM_HandleTypeDef *hlptim, uint32_t Period) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* If clock source is not ULPTIM clock and counter source is external, then it must not be prescaled */ + if ((hlptim->Init.Clock.Source != LPTIM_CLOCKSOURCE_ULPTIM) + && (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL)) + { + /* Check if clock is prescaled */ + assert_param(IS_LPTIM_CLOCK_PRESCALERDIV1(hlptim->Init.Clock.Prescaler)); + /* Set clock prescaler to 0 */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_PRESC; + } + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Counter mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Stop(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Start the Counter mode in interrupt mode. + * @param hlptim LPTIM handle + * @param Period Specifies the Autoreload value. + * This parameter must be a value between 0x0001 and 0xFFFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Start_IT(LPTIM_HandleTypeDef *hlptim, uint32_t Period) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + assert_param(IS_LPTIM_PERIOD(Period)); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Enable EXTI Line interrupt on the LPTIM Wake-up Timer */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_IT(); +#if defined(EXTI_IMR_MR23) + /* Enable rising edge trigger on the LPTIM Wake-up Timer Exti line */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); +#endif /* EXTI_IMR_MR23 */ + + /* If clock source is not ULPTIM clock and counter source is external, then it must not be prescaled */ + if ((hlptim->Init.Clock.Source != LPTIM_CLOCKSOURCE_ULPTIM) + && (hlptim->Init.CounterSource == LPTIM_COUNTERSOURCE_EXTERNAL)) + { + /* Check if clock is prescaled */ + assert_param(IS_LPTIM_CLOCK_PRESCALERDIV1(hlptim->Init.Clock.Prescaler)); + /* Set clock prescaler to 0 */ + hlptim->Instance->CFGR &= ~LPTIM_CFGR_PRESC; + } + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Clear flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Load the period value in the autoreload register */ + __HAL_LPTIM_AUTORELOAD_SET(hlptim, Period); + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Enable Autoreload write complete interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Enable Autoreload match interrupt */ + __HAL_LPTIM_ENABLE_IT(hlptim, LPTIM_IT_ARRM); + + /* Enable the Peripheral */ + __HAL_LPTIM_ENABLE(hlptim); + + /* Start timer in continuous mode */ + __HAL_LPTIM_START_CONTINUOUS(hlptim); + + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Stop the Counter mode in interrupt mode. + * @param hlptim LPTIM handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LPTIM_Counter_Stop_IT(LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + +#if defined(EXTI_IMR_MR23) + /* Disable rising edge trigger on the LPTIM Wake-up Timer Exti line */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_RISING_EDGE(); +#endif /* EXTI_IMR_MR23 */ + + /* Disable EXTI Line interrupt on the LPTIM Wake-up Timer */ + __HAL_LPTIM_WAKEUPTIMER_EXTI_DISABLE_IT(); + + /* Set the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_LPTIM_DISABLE(hlptim); + + if (HAL_LPTIM_GetState(hlptim) == HAL_LPTIM_STATE_TIMEOUT) + { + return HAL_TIMEOUT; + } + + /* Disable Autoreload write complete interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARROK); + + /* Disable Autoreload match interrupt */ + __HAL_LPTIM_DISABLE_IT(hlptim, LPTIM_IT_ARRM); + /* Change the LPTIM state */ + hlptim->State = HAL_LPTIM_STATE_READY; + + /* Return function status */ + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup LPTIM_Exported_Functions_Group3 LPTIM Read operation functions + * @brief Read operation functions. + * +@verbatim + ============================================================================== + ##### LPTIM Read operation functions ##### + ============================================================================== +[..] This section provides LPTIM Reading functions. + (+) Read the counter value. + (+) Read the period (Auto-reload) value. + (+) Read the pulse (Compare)value. +@endverbatim + * @{ + */ + +/** + * @brief Return the current counter value. + * @param hlptim LPTIM handle + * @retval Counter value. + */ +uint32_t HAL_LPTIM_ReadCounter(const LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + return (hlptim->Instance->CNT); +} + +/** + * @brief Return the current Autoreload (Period) value. + * @param hlptim LPTIM handle + * @retval Autoreload value. + */ +uint32_t HAL_LPTIM_ReadAutoReload(const LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + return (hlptim->Instance->ARR); +} + +/** + * @brief Return the current Compare (Pulse) value. + * @param hlptim LPTIM handle + * @retval Compare value. + */ +uint32_t HAL_LPTIM_ReadCompare(const LPTIM_HandleTypeDef *hlptim) +{ + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(hlptim->Instance)); + + return (hlptim->Instance->CMP); +} + +/** + * @} + */ + +/** @defgroup LPTIM_Exported_Functions_Group4 LPTIM IRQ handler and callbacks + * @brief LPTIM IRQ handler. + * +@verbatim + ============================================================================== + ##### LPTIM IRQ handler and callbacks ##### + ============================================================================== +[..] This section provides LPTIM IRQ handler and callback functions called within + the IRQ handler: + (+) LPTIM interrupt request handler + (+) Compare match Callback + (+) Auto-reload match Callback + (+) External trigger event detection Callback + (+) Compare register write complete Callback + (+) Auto-reload register write complete Callback + (+) Up-counting direction change Callback + (+) Down-counting direction change Callback + +@endverbatim + * @{ + */ + +/** + * @brief Handle LPTIM interrupt request. + * @param hlptim LPTIM handle + * @retval None + */ +void HAL_LPTIM_IRQHandler(LPTIM_HandleTypeDef *hlptim) +{ + /* Compare match interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPM) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPM) != RESET) + { + /* Clear Compare match flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPM); + + /* Compare match Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->CompareMatchCallback(hlptim); +#else + HAL_LPTIM_CompareMatchCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Autoreload match interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARRM) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARRM) != RESET) + { + /* Clear Autoreload match flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARRM); + + /* Autoreload match Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->AutoReloadMatchCallback(hlptim); +#else + HAL_LPTIM_AutoReloadMatchCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Trigger detected interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_EXTTRIG) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_EXTTRIG) != RESET) + { + /* Clear Trigger detected flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_EXTTRIG); + + /* Trigger detected callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->TriggerCallback(hlptim); +#else + HAL_LPTIM_TriggerCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Compare write interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPOK) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPOK) != RESET) + { + /* Clear Compare write flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + + /* Compare write Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->CompareWriteCallback(hlptim); +#else + HAL_LPTIM_CompareWriteCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Autoreload write interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARROK) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARROK) != RESET) + { + /* Clear Autoreload write flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + + /* Autoreload write Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->AutoReloadWriteCallback(hlptim); +#else + HAL_LPTIM_AutoReloadWriteCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Direction counter changed from Down to Up interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_UP) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_UP) != RESET) + { + /* Clear Direction counter changed from Down to Up flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_UP); + + /* Direction counter changed from Down to Up Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->DirectionUpCallback(hlptim); +#else + HAL_LPTIM_DirectionUpCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } + + /* Direction counter changed from Up to Down interrupt */ + if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_DOWN) != RESET) + { + if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_DOWN) != RESET) + { + /* Clear Direction counter changed from Up to Down flag */ + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_DOWN); + + /* Direction counter changed from Up to Down Callback */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) + hlptim->DirectionDownCallback(hlptim); +#else + HAL_LPTIM_DirectionDownCallback(hlptim); +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + } + } +#if defined(EXTI_IMR_MR23) + __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG(); +#endif /* EXTI_IMR_MR23 */ +} + +/** + * @brief Compare match callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_CompareMatchCallback could be implemented in the user file + */ +} + +/** + * @brief Autoreload match callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_AutoReloadMatchCallback could be implemented in the user file + */ +} + +/** + * @brief Trigger detected callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_TriggerCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_TriggerCallback could be implemented in the user file + */ +} + +/** + * @brief Compare write callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_CompareWriteCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_CompareWriteCallback could be implemented in the user file + */ +} + +/** + * @brief Autoreload write callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_AutoReloadWriteCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_AutoReloadWriteCallback could be implemented in the user file + */ +} + +/** + * @brief Direction counter changed from Down to Up callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_DirectionUpCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_DirectionUpCallback could be implemented in the user file + */ +} + +/** + * @brief Direction counter changed from Up to Down callback in non-blocking mode. + * @param hlptim LPTIM handle + * @retval None + */ +__weak void HAL_LPTIM_DirectionDownCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hlptim); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LPTIM_DirectionDownCallback could be implemented in the user file + */ +} + +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User LPTIM callback to be used instead of the weak predefined callback + * @param hlptim LPTIM handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_LPTIM_MSPINIT_CB_ID LPTIM Base Msp Init Callback ID + * @arg @ref HAL_LPTIM_MSPDEINIT_CB_ID LPTIM Base Msp DeInit Callback ID + * @arg @ref HAL_LPTIM_COMPARE_MATCH_CB_ID Compare match Callback ID + * @arg @ref HAL_LPTIM_AUTORELOAD_MATCH_CB_ID Auto-reload match Callback ID + * @arg @ref HAL_LPTIM_TRIGGER_CB_ID External trigger event detection Callback ID + * @arg @ref HAL_LPTIM_COMPARE_WRITE_CB_ID Compare register write complete Callback ID + * @arg @ref HAL_LPTIM_AUTORELOAD_WRITE_CB_ID Auto-reload register write complete Callback ID + * @arg @ref HAL_LPTIM_DIRECTION_UP_CB_ID Up-counting direction change Callback ID + * @arg @ref HAL_LPTIM_DIRECTION_DOWN_CB_ID Down-counting direction change Callback ID + * @param pCallback pointer to the callback function + * @retval status + */ +HAL_StatusTypeDef HAL_LPTIM_RegisterCallback(LPTIM_HandleTypeDef *hlptim, + HAL_LPTIM_CallbackIDTypeDef CallbackID, + pLPTIM_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hlptim); + + if (hlptim->State == HAL_LPTIM_STATE_READY) + { + switch (CallbackID) + { + case HAL_LPTIM_MSPINIT_CB_ID : + hlptim->MspInitCallback = pCallback; + break; + + case HAL_LPTIM_MSPDEINIT_CB_ID : + hlptim->MspDeInitCallback = pCallback; + break; + + case HAL_LPTIM_COMPARE_MATCH_CB_ID : + hlptim->CompareMatchCallback = pCallback; + break; + + case HAL_LPTIM_AUTORELOAD_MATCH_CB_ID : + hlptim->AutoReloadMatchCallback = pCallback; + break; + + case HAL_LPTIM_TRIGGER_CB_ID : + hlptim->TriggerCallback = pCallback; + break; + + case HAL_LPTIM_COMPARE_WRITE_CB_ID : + hlptim->CompareWriteCallback = pCallback; + break; + + case HAL_LPTIM_AUTORELOAD_WRITE_CB_ID : + hlptim->AutoReloadWriteCallback = pCallback; + break; + + case HAL_LPTIM_DIRECTION_UP_CB_ID : + hlptim->DirectionUpCallback = pCallback; + break; + + case HAL_LPTIM_DIRECTION_DOWN_CB_ID : + hlptim->DirectionDownCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hlptim->State == HAL_LPTIM_STATE_RESET) + { + switch (CallbackID) + { + case HAL_LPTIM_MSPINIT_CB_ID : + hlptim->MspInitCallback = pCallback; + break; + + case HAL_LPTIM_MSPDEINIT_CB_ID : + hlptim->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hlptim); + + return status; +} + +/** + * @brief Unregister a LPTIM callback + * LLPTIM callback is redirected to the weak predefined callback + * @param hlptim LPTIM handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_LPTIM_MSPINIT_CB_ID LPTIM Base Msp Init Callback ID + * @arg @ref HAL_LPTIM_MSPDEINIT_CB_ID LPTIM Base Msp DeInit Callback ID + * @arg @ref HAL_LPTIM_COMPARE_MATCH_CB_ID Compare match Callback ID + * @arg @ref HAL_LPTIM_AUTORELOAD_MATCH_CB_ID Auto-reload match Callback ID + * @arg @ref HAL_LPTIM_TRIGGER_CB_ID External trigger event detection Callback ID + * @arg @ref HAL_LPTIM_COMPARE_WRITE_CB_ID Compare register write complete Callback ID + * @arg @ref HAL_LPTIM_AUTORELOAD_WRITE_CB_ID Auto-reload register write complete Callback ID + * @arg @ref HAL_LPTIM_DIRECTION_UP_CB_ID Up-counting direction change Callback ID + * @arg @ref HAL_LPTIM_DIRECTION_DOWN_CB_ID Down-counting direction change Callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_LPTIM_UnRegisterCallback(LPTIM_HandleTypeDef *hlptim, + HAL_LPTIM_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hlptim); + + if (hlptim->State == HAL_LPTIM_STATE_READY) + { + switch (CallbackID) + { + case HAL_LPTIM_MSPINIT_CB_ID : + /* Legacy weak MspInit Callback */ + hlptim->MspInitCallback = HAL_LPTIM_MspInit; + break; + + case HAL_LPTIM_MSPDEINIT_CB_ID : + /* Legacy weak Msp DeInit Callback */ + hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit; + break; + + case HAL_LPTIM_COMPARE_MATCH_CB_ID : + /* Legacy weak Compare match Callback */ + hlptim->CompareMatchCallback = HAL_LPTIM_CompareMatchCallback; + break; + + case HAL_LPTIM_AUTORELOAD_MATCH_CB_ID : + /* Legacy weak Auto-reload match Callback */ + hlptim->AutoReloadMatchCallback = HAL_LPTIM_AutoReloadMatchCallback; + break; + + case HAL_LPTIM_TRIGGER_CB_ID : + /* Legacy weak External trigger event detection Callback */ + hlptim->TriggerCallback = HAL_LPTIM_TriggerCallback; + break; + + case HAL_LPTIM_COMPARE_WRITE_CB_ID : + /* Legacy weak Compare register write complete Callback */ + hlptim->CompareWriteCallback = HAL_LPTIM_CompareWriteCallback; + break; + + case HAL_LPTIM_AUTORELOAD_WRITE_CB_ID : + /* Legacy weak Auto-reload register write complete Callback */ + hlptim->AutoReloadWriteCallback = HAL_LPTIM_AutoReloadWriteCallback; + break; + + case HAL_LPTIM_DIRECTION_UP_CB_ID : + /* Legacy weak Up-counting direction change Callback */ + hlptim->DirectionUpCallback = HAL_LPTIM_DirectionUpCallback; + break; + + case HAL_LPTIM_DIRECTION_DOWN_CB_ID : + /* Legacy weak Down-counting direction change Callback */ + hlptim->DirectionDownCallback = HAL_LPTIM_DirectionDownCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hlptim->State == HAL_LPTIM_STATE_RESET) + { + switch (CallbackID) + { + case HAL_LPTIM_MSPINIT_CB_ID : + /* Legacy weak MspInit Callback */ + hlptim->MspInitCallback = HAL_LPTIM_MspInit; + break; + + case HAL_LPTIM_MSPDEINIT_CB_ID : + /* Legacy weak Msp DeInit Callback */ + hlptim->MspDeInitCallback = HAL_LPTIM_MspDeInit; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hlptim); + + return status; +} +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup LPTIM_Group5 Peripheral State functions + * @brief Peripheral State functions. + * +@verbatim + ============================================================================== + ##### Peripheral State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Return the LPTIM handle state. + * @param hlptim LPTIM handle + * @retval HAL state + */ +HAL_LPTIM_StateTypeDef HAL_LPTIM_GetState(LPTIM_HandleTypeDef *hlptim) +{ + /* Return LPTIM handle state */ + return hlptim->State; +} + +/** + * @} + */ + + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup LPTIM_Private_Functions LPTIM Private Functions + * @{ + */ +#if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1) +/** + * @brief Reset interrupt callbacks to the legacy weak callbacks. + * @param lptim pointer to a LPTIM_HandleTypeDef structure that contains + * the configuration information for LPTIM module. + * @retval None + */ +static void LPTIM_ResetCallback(LPTIM_HandleTypeDef *lptim) +{ + /* Reset the LPTIM callback to the legacy weak callbacks */ + lptim->CompareMatchCallback = HAL_LPTIM_CompareMatchCallback; + lptim->AutoReloadMatchCallback = HAL_LPTIM_AutoReloadMatchCallback; + lptim->TriggerCallback = HAL_LPTIM_TriggerCallback; + lptim->CompareWriteCallback = HAL_LPTIM_CompareWriteCallback; + lptim->AutoReloadWriteCallback = HAL_LPTIM_AutoReloadWriteCallback; + lptim->DirectionUpCallback = HAL_LPTIM_DirectionUpCallback; + lptim->DirectionDownCallback = HAL_LPTIM_DirectionDownCallback; +} +#endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */ + +/** + * @brief LPTimer Wait for flag set + * @param hlptim pointer to a LPTIM_HandleTypeDef structure that contains + * the configuration information for LPTIM module. + * @param flag The lptim flag + * @retval HAL status + */ +static HAL_StatusTypeDef LPTIM_WaitForFlag(LPTIM_HandleTypeDef *hlptim, uint32_t flag) +{ + HAL_StatusTypeDef result = HAL_OK; + uint32_t count = TIMEOUT * (SystemCoreClock / 20UL / 1000UL); + do + { + count--; + if (count == 0UL) + { + result = HAL_TIMEOUT; + } + } while ((!(__HAL_LPTIM_GET_FLAG((hlptim), (flag)))) && (count != 0UL)); + + return result; +} + +/** + * @brief Disable LPTIM HW instance. + * @param hlptim pointer to a LPTIM_HandleTypeDef structure that contains + * the configuration information for LPTIM module. + * @note The following sequence is required to solve LPTIM disable HW limitation. + * Please check Errata Sheet ES0335 for more details under "MCU may remain + * stuck in LPTIM interrupt when entering Stop mode" section. + * @retval None + */ +void LPTIM_Disable(LPTIM_HandleTypeDef *hlptim) +{ + uint32_t tmpclksource = 0; + uint32_t tmpIER; + uint32_t tmpCFGR; + uint32_t tmpCMP; + uint32_t tmpARR; + uint32_t primask_bit; + uint32_t tmpOR; + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1) ; + + /*********** Save LPTIM Config ***********/ + /* Save LPTIM source clock */ + switch ((uint32_t)hlptim->Instance) + { + case LPTIM1_BASE: + tmpclksource = __HAL_RCC_GET_LPTIM1_SOURCE(); + break; + default: + break; + } + + /* Save LPTIM configuration registers */ + tmpIER = hlptim->Instance->IER; + tmpCFGR = hlptim->Instance->CFGR; + tmpCMP = hlptim->Instance->CMP; + tmpARR = hlptim->Instance->ARR; + tmpOR = hlptim->Instance->OR; + + /*********** Reset LPTIM ***********/ + switch ((uint32_t)hlptim->Instance) + { + case LPTIM1_BASE: + __HAL_RCC_LPTIM1_FORCE_RESET(); + __HAL_RCC_LPTIM1_RELEASE_RESET(); + break; + default: + break; + } + + /*********** Restore LPTIM Config ***********/ + if ((tmpCMP != 0UL) || (tmpARR != 0UL)) + { + /* Force LPTIM source kernel clock from APB */ + switch ((uint32_t)hlptim->Instance) + { + case LPTIM1_BASE: + __HAL_RCC_LPTIM1_CONFIG(RCC_LPTIM1CLKSOURCE_PCLK1); + break; + default: + break; + } + + if (tmpCMP != 0UL) + { + /* Restore CMP register (LPTIM should be enabled first) */ + hlptim->Instance->CR |= LPTIM_CR_ENABLE; + hlptim->Instance->CMP = tmpCMP; + + /* Wait for the completion of the write operation to the LPTIM_CMP register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_CMPOK) == HAL_TIMEOUT) + { + hlptim->State = HAL_LPTIM_STATE_TIMEOUT; + } + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK); + } + + if (tmpARR != 0UL) + { + /* Restore ARR register (LPTIM should be enabled first) */ + hlptim->Instance->CR |= LPTIM_CR_ENABLE; + hlptim->Instance->ARR = tmpARR; + + /* Wait for the completion of the write operation to the LPTIM_ARR register */ + if (LPTIM_WaitForFlag(hlptim, LPTIM_FLAG_ARROK) == HAL_TIMEOUT) + { + hlptim->State = HAL_LPTIM_STATE_TIMEOUT; + } + + __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK); + } + + /* Restore LPTIM source kernel clock */ + switch ((uint32_t)hlptim->Instance) + { + case LPTIM1_BASE: + __HAL_RCC_LPTIM1_CONFIG(tmpclksource); + break; + default: + break; + } + } + + /* Restore configuration registers (LPTIM should be disabled first) */ + hlptim->Instance->CR &= ~(LPTIM_CR_ENABLE); + hlptim->Instance->IER = tmpIER; + hlptim->Instance->CFGR = tmpCFGR; + hlptim->Instance->OR = tmpOR; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); +} +/** + * @} + */ +#endif /* LPTIM1 */ + +#endif /* HAL_LPTIM_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c new file mode 100644 index 0000000..fcc5fa1 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc.c @@ -0,0 +1,2215 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_ltdc.c + * @author MCD Application Team + * @brief LTDC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the LTDC peripheral: + * + 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 LTDC HAL driver can be used as follows: + + (#) Declare a LTDC_HandleTypeDef handle structure, for example: LTDC_HandleTypeDef hltdc; + + (#) Initialize the LTDC low level resources by implementing the HAL_LTDC_MspInit() API: + (##) Enable the LTDC interface clock + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the LTDC interrupt priority + (+++) Enable the NVIC LTDC IRQ Channel + + (#) Initialize the required configuration through the following parameters: + the LTDC timing, the horizontal and vertical polarity, the pixel clock polarity, + Data Enable polarity and the LTDC background color value using HAL_LTDC_Init() function + + *** Configuration *** + ========================= + [..] + (#) Program the required configuration through the following parameters: + the pixel format, the blending factors, input alpha value, the window size + and the image size using HAL_LTDC_ConfigLayer() function for foreground + or/and background layer. + + (#) Optionally, configure and enable the CLUT using HAL_LTDC_ConfigCLUT() and + HAL_LTDC_EnableCLUT functions. + + (#) Optionally, enable the Dither using HAL_LTDC_EnableDither(). + + (#) Optionally, configure and enable the Color keying using HAL_LTDC_ConfigColorKeying() + and HAL_LTDC_EnableColorKeying functions. + + (#) Optionally, configure LineInterrupt using HAL_LTDC_ProgramLineEvent() + function + + (#) If needed, reconfigure and change the pixel format value, the alpha value + value, the window size, the window position and the layer start address + for foreground or/and background layer using respectively the following + functions: HAL_LTDC_SetPixelFormat(), HAL_LTDC_SetAlpha(), HAL_LTDC_SetWindowSize(), + HAL_LTDC_SetWindowPosition() and HAL_LTDC_SetAddress(). + + (#) Variant functions with _NoReload suffix allows to set the LTDC configuration/settings without immediate reload. + This is useful in case when the program requires to modify serval LTDC settings (on one or both layers) + then applying(reload) these settings in one shot by calling the function HAL_LTDC_Reload(). + + After calling the _NoReload functions to set different color/format/layer settings, + the program shall call the function HAL_LTDC_Reload() to apply(reload) these settings. + Function HAL_LTDC_Reload() can be called with the parameter ReloadType set to LTDC_RELOAD_IMMEDIATE if + an immediate reload is required. + Function HAL_LTDC_Reload() can be called with the parameter ReloadType set to LTDC_RELOAD_VERTICAL_BLANKING if + the reload should be done in the next vertical blanking period, + this option allows to avoid display flicker by applying the new settings during the vertical blanking period. + + + (#) To control LTDC state you can use the following function: HAL_LTDC_GetState() + + *** LTDC HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in LTDC HAL driver. + + (+) __HAL_LTDC_ENABLE: Enable the LTDC. + (+) __HAL_LTDC_DISABLE: Disable the LTDC. + (+) __HAL_LTDC_LAYER_ENABLE: Enable an LTDC Layer. + (+) __HAL_LTDC_LAYER_DISABLE: Disable an LTDC Layer. + (+) __HAL_LTDC_RELOAD_IMMEDIATE_CONFIG: Reload Layer Configuration. + (+) __HAL_LTDC_GET_FLAG: Get the LTDC pending flags. + (+) __HAL_LTDC_CLEAR_FLAG: Clear the LTDC pending flags. + (+) __HAL_LTDC_ENABLE_IT: Enable the specified LTDC interrupts. + (+) __HAL_LTDC_DISABLE_IT: Disable the specified LTDC interrupts. + (+) __HAL_LTDC_GET_IT_SOURCE: Check whether the specified LTDC interrupt has occurred or not. + + [..] + (@) You can refer to the LTDC HAL driver header file for more useful macros + + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_LTDC_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use function HAL_LTDC_RegisterCallback() to register a callback. + + [..] + Function HAL_LTDC_RegisterCallback() allows to register following callbacks: + (+) LineEventCallback : LTDC Line Event Callback. + (+) ReloadEventCallback : LTDC Reload Event Callback. + (+) ErrorCallback : LTDC Error Callback + (+) MspInitCallback : LTDC MspInit. + (+) MspDeInitCallback : LTDC MspDeInit. + [..] + This function takes as parameters the HAL peripheral handle, the callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_LTDC_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_LTDC_UnRegisterCallback() takes as parameters the HAL peripheral handle + and the callback ID. + [..] + This function allows to reset following callbacks: + (+) LineEventCallback : LTDC Line Event Callback + (+) ReloadEventCallback : LTDC Reload Event Callback + (+) ErrorCallback : LTDC Error Callback + (+) MspInitCallback : LTDC MspInit + (+) MspDeInitCallback : LTDC MspDeInit. + + [..] + By default, after the HAL_LTDC_Init and when the state is HAL_LTDC_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_LTDC_LineEventCallback(), HAL_LTDC_ErrorCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak (surcharged) functions in the HAL_LTDC_Init() and HAL_LTDC_DeInit() + only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_LTDC_Init() and HAL_LTDC_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_LTDC_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_LTDC_STATE_READY or HAL_LTDC_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_LTDC_RegisterCallback() before calling HAL_LTDC_DeInit() + or HAL_LTDC_Init() function. + + [..] + When the compilation define USE_HAL_LTDC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_LTDC_MODULE_ENABLED + +#if defined (LTDC) + +/** @defgroup LTDC LTDC + * @brief LTDC HAL module driver + * @{ + */ + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define LTDC_TIMEOUT_VALUE ((uint32_t)100U) /* 100ms */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void LTDC_SetConfig(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx); +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup LTDC_Exported_Functions LTDC Exported Functions + * @{ + */ + +/** @defgroup LTDC_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the LTDC + (+) De-initialize the LTDC + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the LTDC according to the specified parameters in the LTDC_InitTypeDef. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc) +{ + uint32_t tmp; + uint32_t tmp1; + + /* Check the LTDC peripheral state */ + if (hltdc == NULL) + { + return HAL_ERROR; + } + + /* Check function parameters */ + assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance)); + assert_param(IS_LTDC_HSYNC(hltdc->Init.HorizontalSync)); + assert_param(IS_LTDC_VSYNC(hltdc->Init.VerticalSync)); + assert_param(IS_LTDC_AHBP(hltdc->Init.AccumulatedHBP)); + assert_param(IS_LTDC_AVBP(hltdc->Init.AccumulatedVBP)); + assert_param(IS_LTDC_AAH(hltdc->Init.AccumulatedActiveH)); + assert_param(IS_LTDC_AAW(hltdc->Init.AccumulatedActiveW)); + assert_param(IS_LTDC_TOTALH(hltdc->Init.TotalHeigh)); + assert_param(IS_LTDC_TOTALW(hltdc->Init.TotalWidth)); + assert_param(IS_LTDC_HSPOL(hltdc->Init.HSPolarity)); + assert_param(IS_LTDC_VSPOL(hltdc->Init.VSPolarity)); + assert_param(IS_LTDC_DEPOL(hltdc->Init.DEPolarity)); + assert_param(IS_LTDC_PCPOL(hltdc->Init.PCPolarity)); + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + if (hltdc->State == HAL_LTDC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hltdc->Lock = HAL_UNLOCKED; + + /* Reset the LTDC callback to the legacy weak callbacks */ + hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */ + hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */ + hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hltdc->MspInitCallback == NULL) + { + hltdc->MspInitCallback = HAL_LTDC_MspInit; + } + /* Init the low level hardware */ + hltdc->MspInitCallback(hltdc); + } +#else + if (hltdc->State == HAL_LTDC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hltdc->Lock = HAL_UNLOCKED; + /* Init the low level hardware */ + HAL_LTDC_MspInit(hltdc); + } +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Configure the HS, VS, DE and PC polarity */ + hltdc->Instance->GCR &= ~(LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL | LTDC_GCR_PCPOL); + hltdc->Instance->GCR |= (uint32_t)(hltdc->Init.HSPolarity | hltdc->Init.VSPolarity | \ + hltdc->Init.DEPolarity | hltdc->Init.PCPolarity); + + /* Set Synchronization size */ + hltdc->Instance->SSCR &= ~(LTDC_SSCR_VSH | LTDC_SSCR_HSW); + tmp = (hltdc->Init.HorizontalSync << 16U); + hltdc->Instance->SSCR |= (tmp | hltdc->Init.VerticalSync); + + /* Set Accumulated Back porch */ + hltdc->Instance->BPCR &= ~(LTDC_BPCR_AVBP | LTDC_BPCR_AHBP); + tmp = (hltdc->Init.AccumulatedHBP << 16U); + hltdc->Instance->BPCR |= (tmp | hltdc->Init.AccumulatedVBP); + + /* Set Accumulated Active Width */ + hltdc->Instance->AWCR &= ~(LTDC_AWCR_AAH | LTDC_AWCR_AAW); + tmp = (hltdc->Init.AccumulatedActiveW << 16U); + hltdc->Instance->AWCR |= (tmp | hltdc->Init.AccumulatedActiveH); + + /* Set Total Width */ + hltdc->Instance->TWCR &= ~(LTDC_TWCR_TOTALH | LTDC_TWCR_TOTALW); + tmp = (hltdc->Init.TotalWidth << 16U); + hltdc->Instance->TWCR |= (tmp | hltdc->Init.TotalHeigh); + + /* Set the background color value */ + tmp = ((uint32_t)(hltdc->Init.Backcolor.Green) << 8U); + tmp1 = ((uint32_t)(hltdc->Init.Backcolor.Red) << 16U); + hltdc->Instance->BCCR &= ~(LTDC_BCCR_BCBLUE | LTDC_BCCR_BCGREEN | LTDC_BCCR_BCRED); + hltdc->Instance->BCCR |= (tmp1 | tmp | hltdc->Init.Backcolor.Blue); + + /* Enable the Transfer Error and FIFO underrun interrupts */ + __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_TE | LTDC_IT_FU); + + /* Enable LTDC by setting LTDCEN bit */ + __HAL_LTDC_ENABLE(hltdc); + + /* Initialize the error code */ + hltdc->ErrorCode = HAL_LTDC_ERROR_NONE; + + /* Initialize the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + return HAL_OK; +} + +/** + * @brief De-initialize the LTDC peripheral. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ + +HAL_StatusTypeDef HAL_LTDC_DeInit(LTDC_HandleTypeDef *hltdc) +{ + uint32_t tickstart; + + /* Check the LTDC peripheral state */ + if (hltdc == NULL) + { + return HAL_ERROR; + } + + /* Check function parameters */ + assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance)); + + /* Disable LTDC Layer 1 */ + __HAL_LTDC_LAYER_DISABLE(hltdc, LTDC_LAYER_1); + +#if defined(LTDC_Layer2_BASE) + /* Disable LTDC Layer 2 */ + __HAL_LTDC_LAYER_DISABLE(hltdc, LTDC_LAYER_2); +#endif /* LTDC_Layer2_BASE */ + + /* Reload during vertical blanking period */ + __HAL_LTDC_VERTICAL_BLANKING_RELOAD_CONFIG(hltdc); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for VSYNC Interrupt */ + while (READ_BIT(hltdc->Instance->CDSR, LTDC_CDSR_VSYNCS) == 0U) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > LTDC_TIMEOUT_VALUE) + { + break; + } + } + + /* Disable LTDC */ + __HAL_LTDC_DISABLE(hltdc); + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + if (hltdc->MspDeInitCallback == NULL) + { + hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit; + } + /* DeInit the low level hardware */ + hltdc->MspDeInitCallback(hltdc); +#else + /* DeInit the low level hardware */ + HAL_LTDC_MspDeInit(hltdc); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + + /* Initialize the error code */ + hltdc->ErrorCode = HAL_LTDC_ERROR_NONE; + + /* Initialize the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Initialize the LTDC MSP. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ +__weak void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LTDC_MspInit could be implemented in the user file + */ +} + +/** + * @brief De-initialize the LTDC MSP. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ +__weak void HAL_LTDC_MspDeInit(LTDC_HandleTypeDef *hltdc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LTDC_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User LTDC Callback + * To be used instead of the weak predefined callback + * @param hltdc ltdc handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_LTDC_LINE_EVENT_CB_ID Line Event Callback ID + * @arg @ref HAL_LTDC_RELOAD_EVENT_CB_ID Reload Event Callback ID + * @arg @ref HAL_LTDC_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_LTDC_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_LTDC_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_LTDC_RegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID, + pLTDC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hltdc); + + if (hltdc->State == HAL_LTDC_STATE_READY) + { + switch (CallbackID) + { + case HAL_LTDC_LINE_EVENT_CB_ID : + hltdc->LineEventCallback = pCallback; + break; + + case HAL_LTDC_RELOAD_EVENT_CB_ID : + hltdc->ReloadEventCallback = pCallback; + break; + + case HAL_LTDC_ERROR_CB_ID : + hltdc->ErrorCallback = pCallback; + break; + + case HAL_LTDC_MSPINIT_CB_ID : + hltdc->MspInitCallback = pCallback; + break; + + case HAL_LTDC_MSPDEINIT_CB_ID : + hltdc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hltdc->State == HAL_LTDC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_LTDC_MSPINIT_CB_ID : + hltdc->MspInitCallback = pCallback; + break; + + case HAL_LTDC_MSPDEINIT_CB_ID : + hltdc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hltdc); + + return status; +} + +/** + * @brief Unregister an LTDC Callback + * LTDC callback is redirected to the weak predefined callback + * @param hltdc ltdc handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_LTDC_LINE_EVENT_CB_ID Line Event Callback ID + * @arg @ref HAL_LTDC_RELOAD_EVENT_CB_ID Reload Event Callback ID + * @arg @ref HAL_LTDC_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_LTDC_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_LTDC_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_LTDC_UnRegisterCallback(LTDC_HandleTypeDef *hltdc, HAL_LTDC_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hltdc); + + if (hltdc->State == HAL_LTDC_STATE_READY) + { + switch (CallbackID) + { + case HAL_LTDC_LINE_EVENT_CB_ID : + hltdc->LineEventCallback = HAL_LTDC_LineEventCallback; /* Legacy weak LineEventCallback */ + break; + + case HAL_LTDC_RELOAD_EVENT_CB_ID : + hltdc->ReloadEventCallback = HAL_LTDC_ReloadEventCallback; /* Legacy weak ReloadEventCallback */ + break; + + case HAL_LTDC_ERROR_CB_ID : + hltdc->ErrorCallback = HAL_LTDC_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_LTDC_MSPINIT_CB_ID : + hltdc->MspInitCallback = HAL_LTDC_MspInit; /* Legcay weak MspInit Callback */ + break; + + case HAL_LTDC_MSPDEINIT_CB_ID : + hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit; /* Legcay weak MspDeInit Callback */ + break; + + default : + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hltdc->State == HAL_LTDC_STATE_RESET) + { + switch (CallbackID) + { + case HAL_LTDC_MSPINIT_CB_ID : + hltdc->MspInitCallback = HAL_LTDC_MspInit; /* Legcay weak MspInit Callback */ + break; + + case HAL_LTDC_MSPDEINIT_CB_ID : + hltdc->MspDeInitCallback = HAL_LTDC_MspDeInit; /* Legcay weak MspDeInit Callback */ + break; + + default : + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hltdc); + + return status; +} +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup LTDC_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] This section provides function allowing to: + (+) Handle LTDC interrupt request + +@endverbatim + * @{ + */ +/** + * @brief Handle LTDC interrupt request. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval HAL status + */ +void HAL_LTDC_IRQHandler(LTDC_HandleTypeDef *hltdc) +{ + uint32_t isrflags = READ_REG(hltdc->Instance->ISR); + uint32_t itsources = READ_REG(hltdc->Instance->IER); + + /* Transfer Error Interrupt management ***************************************/ + if (((isrflags & LTDC_ISR_TERRIF) != 0U) && ((itsources & LTDC_IER_TERRIE) != 0U)) + { + /* Disable the transfer Error interrupt */ + __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_TE); + + /* Clear the transfer error flag */ + __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_TE); + + /* Update error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_TE; + + /* Change LTDC state */ + hltdc->State = HAL_LTDC_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + /* Transfer error Callback */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hltdc->ErrorCallback(hltdc); +#else + /* Call legacy error callback*/ + HAL_LTDC_ErrorCallback(hltdc); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + } + + /* FIFO underrun Interrupt management ***************************************/ + if (((isrflags & LTDC_ISR_FUIF) != 0U) && ((itsources & LTDC_IER_FUIE) != 0U)) + { + /* Disable the FIFO underrun interrupt */ + __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_FU); + + /* Clear the FIFO underrun flag */ + __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_FU); + + /* Update error code */ + hltdc->ErrorCode |= HAL_LTDC_ERROR_FU; + + /* Change LTDC state */ + hltdc->State = HAL_LTDC_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + /* Transfer error Callback */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + /*Call registered error callback*/ + hltdc->ErrorCallback(hltdc); +#else + /* Call legacy error callback*/ + HAL_LTDC_ErrorCallback(hltdc); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + } + + /* Line Interrupt management ************************************************/ + if (((isrflags & LTDC_ISR_LIF) != 0U) && ((itsources & LTDC_IER_LIE) != 0U)) + { + /* Disable the Line interrupt */ + __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_LI); + + /* Clear the Line interrupt flag */ + __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_LI); + + /* Change LTDC state */ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + /* Line interrupt Callback */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + /*Call registered Line Event callback */ + hltdc->LineEventCallback(hltdc); +#else + /*Call Legacy Line Event callback */ + HAL_LTDC_LineEventCallback(hltdc); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + } + + /* Register reload Interrupt management ***************************************/ + if (((isrflags & LTDC_ISR_RRIF) != 0U) && ((itsources & LTDC_IER_RRIE) != 0U)) + { + /* Disable the register reload interrupt */ + __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_RR); + + /* Clear the register reload flag */ + __HAL_LTDC_CLEAR_FLAG(hltdc, LTDC_FLAG_RR); + + /* Change LTDC state */ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + /* Reload interrupt Callback */ +#if (USE_HAL_LTDC_REGISTER_CALLBACKS == 1) + /*Call registered reload Event callback */ + hltdc->ReloadEventCallback(hltdc); +#else + /*Call Legacy Reload Event callback */ + HAL_LTDC_ReloadEventCallback(hltdc); +#endif /* USE_HAL_LTDC_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Error LTDC callback. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ +__weak void HAL_LTDC_ErrorCallback(LTDC_HandleTypeDef *hltdc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LTDC_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Line Event callback. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ +__weak void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef *hltdc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LTDC_LineEventCallback could be implemented in the user file + */ +} + +/** + * @brief Reload Event callback. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval None + */ +__weak void HAL_LTDC_ReloadEventCallback(LTDC_HandleTypeDef *hltdc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hltdc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_LTDC_ReloadEvenCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup LTDC_Exported_Functions_Group3 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure the LTDC foreground or/and background parameters. + (+) Set the active layer. + (+) Configure the color keying. + (+) Configure the C-LUT. + (+) Enable / Disable the color keying. + (+) Enable / Disable the C-LUT. + (+) Update the layer position. + (+) Update the layer size. + (+) Update pixel format on the fly. + (+) Update transparency on the fly. + (+) Update address on the fly. + +@endverbatim + * @{ + */ + +/** + * @brief Configure the LTDC Layer according to the specified + * parameters in the LTDC_InitTypeDef and create the associated handle. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param pLayerCfg pointer to a LTDC_LayerCfgTypeDef structure that contains + * the configuration information for the Layer. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_HCONFIGST(pLayerCfg->WindowX0)); + assert_param(IS_LTDC_HCONFIGSP(pLayerCfg->WindowX1)); + assert_param(IS_LTDC_VCONFIGST(pLayerCfg->WindowY0)); + assert_param(IS_LTDC_VCONFIGSP(pLayerCfg->WindowY1)); + assert_param(IS_LTDC_PIXEL_FORMAT(pLayerCfg->PixelFormat)); + assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha)); + assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha0)); + assert_param(IS_LTDC_BLENDING_FACTOR1(pLayerCfg->BlendingFactor1)); + assert_param(IS_LTDC_BLENDING_FACTOR2(pLayerCfg->BlendingFactor2)); + assert_param(IS_LTDC_CFBLL(pLayerCfg->ImageWidth)); + assert_param(IS_LTDC_CFBLNBR(pLayerCfg->ImageHeight)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Copy new layer configuration into handle structure */ + hltdc->LayerCfg[LayerIdx] = *pLayerCfg; + + /* Configure the LTDC Layer */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Initialize the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Configure the color keying. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param RGBValue the color key value + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Configure the default color values */ + LTDC_LAYER(hltdc, LayerIdx)->CKCR &= ~(LTDC_LxCKCR_CKBLUE | LTDC_LxCKCR_CKGREEN | LTDC_LxCKCR_CKRED); + LTDC_LAYER(hltdc, LayerIdx)->CKCR = RGBValue; + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Load the color lookup table. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param pCLUT pointer to the color lookup table address. + * @param CLUTSize the color lookup table size. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ConfigCLUT(LTDC_HandleTypeDef *hltdc, uint32_t *pCLUT, uint32_t CLUTSize, uint32_t LayerIdx) +{ + uint32_t tmp; + uint32_t counter; + uint32_t *pcolorlut = pCLUT; + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + for (counter = 0U; (counter < CLUTSize); counter++) + { + if (hltdc->LayerCfg[LayerIdx].PixelFormat == LTDC_PIXEL_FORMAT_AL44) + { + tmp = (((counter + (16U * counter)) << 24U) | ((uint32_t)(*pcolorlut) & 0xFFU) | \ + ((uint32_t)(*pcolorlut) & 0xFF00U) | ((uint32_t)(*pcolorlut) & 0xFF0000U)); + } + else + { + tmp = ((counter << 24U) | ((uint32_t)(*pcolorlut) & 0xFFU) | \ + ((uint32_t)(*pcolorlut) & 0xFF00U) | ((uint32_t)(*pcolorlut) & 0xFF0000U)); + } + + pcolorlut++; + + /* Specifies the C-LUT address and RGB value */ + LTDC_LAYER(hltdc, LayerIdx)->CLUTWR = tmp; + } + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Enable the color keying. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_EnableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Enable LTDC color keying by setting COLKEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_COLKEN; + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Disable the color keying. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_DisableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable LTDC color keying by setting COLKEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_COLKEN; + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Enable the color lookup table. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_EnableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Enable LTDC color lookup table by setting CLUTEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_CLUTEN; + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Disable the color lookup table. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_DisableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable LTDC color lookup table by setting CLUTEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_CLUTEN; + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Enable Dither. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_LTDC_EnableDither(LTDC_HandleTypeDef *hltdc) +{ + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Enable Dither by setting DTEN bit */ + LTDC->GCR |= (uint32_t)LTDC_GCR_DEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Disable Dither. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval HAL status + */ + +HAL_StatusTypeDef HAL_LTDC_DisableDither(LTDC_HandleTypeDef *hltdc) +{ + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable Dither by setting DTEN bit */ + LTDC->GCR &= ~(uint32_t)LTDC_GCR_DEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Set the LTDC window size. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param XSize LTDC Pixel per line + * @param YSize LTDC Line number + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetWindowSize(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters (Layers parameters)*/ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_CFBLL(XSize)); + assert_param(IS_LTDC_CFBLNBR(YSize)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* update horizontal stop */ + pLayerCfg->WindowX1 = XSize + pLayerCfg->WindowX0; + + /* update vertical stop */ + pLayerCfg->WindowY1 = YSize + pLayerCfg->WindowY0; + + /* Reconfigures the color frame buffer pitch in byte */ + pLayerCfg->ImageWidth = XSize; + + /* Reconfigures the frame buffer line number */ + pLayerCfg->ImageHeight = YSize; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Set the LTDC window position. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param X0 LTDC window X offset + * @param Y0 LTDC window Y offset + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetWindowPosition(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_CFBLL(X0)); + assert_param(IS_LTDC_CFBLNBR(Y0)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* update horizontal start/stop */ + pLayerCfg->WindowX0 = X0; + pLayerCfg->WindowX1 = X0 + pLayerCfg->ImageWidth; + + /* update vertical start/stop */ + pLayerCfg->WindowY0 = Y0; + pLayerCfg->WindowY1 = Y0 + pLayerCfg->ImageHeight; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reconfigure the pixel format. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Pixelformat new pixel format value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetPixelFormat(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_PIXEL_FORMAT(Pixelformat)); + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the pixel format */ + pLayerCfg->PixelFormat = Pixelformat; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reconfigure the layer alpha value. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Alpha new alpha value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetAlpha(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_ALPHA(Alpha)); + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the Alpha value */ + pLayerCfg->Alpha = Alpha; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} +/** + * @brief Reconfigure the frame buffer Address. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Address new address value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetAddress(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the Address */ + pLayerCfg->FBStartAdress = Address; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Set the Immediate Reload type */ + hltdc->Instance->SRCR = LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Function used to reconfigure the pitch for specific cases where the attached LayerIdx buffer have a width + * that is larger than the one intended to be displayed on screen. Example of a buffer 800x480 attached to + * layer for which we want to read and display on screen only a portion 320x240 taken in the center + * of the buffer. + * The pitch in pixels will be in that case 800 pixels and not 320 pixels as initially configured by previous + * call to HAL_LTDC_ConfigLayer(). + * @note This function should be called only after a previous call to HAL_LTDC_ConfigLayer() to modify the default + * pitch configured by HAL_LTDC_ConfigLayer() when required (refer to example described just above). + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LinePitchInPixels New line pitch in pixels to configure for LTDC layer 'LayerIdx'. + * @param LayerIdx LTDC layer index concerned by the modification of line pitch. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetPitch(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx) +{ + uint32_t tmp; + uint32_t pitchUpdate; + uint32_t pixelFormat; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* get LayerIdx used pixel format */ + pixelFormat = hltdc->LayerCfg[LayerIdx].PixelFormat; + + if (pixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) + { + tmp = 4U; + } + else if (pixelFormat == LTDC_PIXEL_FORMAT_RGB888) + { + tmp = 3U; + } + else if ((pixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_AL88)) + { + tmp = 2U; + } + else + { + tmp = 1U; + } + + pitchUpdate = ((LinePitchInPixels * tmp) << 16U); + + /* Clear previously set standard pitch */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~LTDC_LxCFBLR_CFBP; + + /* Set the Reload type as immediate update of LTDC pitch configured above */ + LTDC->SRCR |= LTDC_SRCR_IMR; + + /* Set new line pitch value */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLR |= pitchUpdate; + + /* Set the Reload type as immediate update of LTDC pitch configured above */ + LTDC->SRCR |= LTDC_SRCR_IMR; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Define the position of the line interrupt. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Line Line Interrupt Position. + * @note User application may resort to HAL_LTDC_LineEventCallback() at line interrupt generation. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ProgramLineEvent(LTDC_HandleTypeDef *hltdc, uint32_t Line) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LIPOS(Line)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable the Line interrupt */ + __HAL_LTDC_DISABLE_IT(hltdc, LTDC_IT_LI); + + /* Set the Line Interrupt position */ + LTDC->LIPCR = (uint32_t)Line; + + /* Enable the Line interrupt */ + __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_LI); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reload LTDC Layers configuration. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param ReloadType This parameter can be one of the following values : + * LTDC_RELOAD_IMMEDIATE : Immediate Reload + * LTDC_RELOAD_VERTICAL_BLANKING : Reload in the next Vertical Blanking + * @note User application may resort to HAL_LTDC_ReloadEventCallback() at reload interrupt generation. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_Reload(LTDC_HandleTypeDef *hltdc, uint32_t ReloadType) +{ + /* Check the parameters */ + assert_param(IS_LTDC_RELOAD(ReloadType)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Enable the Reload interrupt */ + __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_RR); + + /* Apply Reload type */ + hltdc->Instance->SRCR = ReloadType; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Configure the LTDC Layer according to the specified without reloading + * parameters in the LTDC_InitTypeDef and create the associated handle. + * Variant of the function HAL_LTDC_ConfigLayer without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param pLayerCfg pointer to a LTDC_LayerCfgTypeDef structure that contains + * the configuration information for the Layer. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ConfigLayer_NoReload(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, + uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_HCONFIGST(pLayerCfg->WindowX0)); + assert_param(IS_LTDC_HCONFIGSP(pLayerCfg->WindowX1)); + assert_param(IS_LTDC_VCONFIGST(pLayerCfg->WindowY0)); + assert_param(IS_LTDC_VCONFIGSP(pLayerCfg->WindowY1)); + assert_param(IS_LTDC_PIXEL_FORMAT(pLayerCfg->PixelFormat)); + assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha)); + assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha0)); + assert_param(IS_LTDC_BLENDING_FACTOR1(pLayerCfg->BlendingFactor1)); + assert_param(IS_LTDC_BLENDING_FACTOR2(pLayerCfg->BlendingFactor2)); + assert_param(IS_LTDC_CFBLL(pLayerCfg->ImageWidth)); + assert_param(IS_LTDC_CFBLNBR(pLayerCfg->ImageHeight)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Copy new layer configuration into handle structure */ + hltdc->LayerCfg[LayerIdx] = *pLayerCfg; + + /* Configure the LTDC Layer */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Initialize the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Set the LTDC window size without reloading. + * Variant of the function HAL_LTDC_SetWindowSize without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param XSize LTDC Pixel per line + * @param YSize LTDC Line number + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetWindowSize_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, + uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters (Layers parameters)*/ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_CFBLL(XSize)); + assert_param(IS_LTDC_CFBLNBR(YSize)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* update horizontal stop */ + pLayerCfg->WindowX1 = XSize + pLayerCfg->WindowX0; + + /* update vertical stop */ + pLayerCfg->WindowY1 = YSize + pLayerCfg->WindowY0; + + /* Reconfigures the color frame buffer pitch in byte */ + pLayerCfg->ImageWidth = XSize; + + /* Reconfigures the frame buffer line number */ + pLayerCfg->ImageHeight = YSize; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Set the LTDC window position without reloading. + * Variant of the function HAL_LTDC_SetWindowPosition without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param X0 LTDC window X offset + * @param Y0 LTDC window Y offset + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetWindowPosition_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, + uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + assert_param(IS_LTDC_CFBLL(X0)); + assert_param(IS_LTDC_CFBLNBR(Y0)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* update horizontal start/stop */ + pLayerCfg->WindowX0 = X0; + pLayerCfg->WindowX1 = X0 + pLayerCfg->ImageWidth; + + /* update vertical start/stop */ + pLayerCfg->WindowY0 = Y0; + pLayerCfg->WindowY1 = Y0 + pLayerCfg->ImageHeight; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reconfigure the pixel format without reloading. + * Variant of the function HAL_LTDC_SetPixelFormat without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDfef structure that contains + * the configuration information for the LTDC. + * @param Pixelformat new pixel format value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetPixelFormat_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_PIXEL_FORMAT(Pixelformat)); + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the pixel format */ + pLayerCfg->PixelFormat = Pixelformat; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reconfigure the layer alpha value without reloading. + * Variant of the function HAL_LTDC_SetAlpha without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Alpha new alpha value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetAlpha_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_ALPHA(Alpha)); + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the Alpha value */ + pLayerCfg->Alpha = Alpha; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Reconfigure the frame buffer Address without reloading. + * Variant of the function HAL_LTDC_SetAddress without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param Address new address value. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetAddress_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx) +{ + LTDC_LayerCfgTypeDef *pLayerCfg; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Get layer configuration from handle structure */ + pLayerCfg = &hltdc->LayerCfg[LayerIdx]; + + /* Reconfigure the Address */ + pLayerCfg->FBStartAdress = Address; + + /* Set LTDC parameters */ + LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx); + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Function used to reconfigure the pitch for specific cases where the attached LayerIdx buffer have a width + * that is larger than the one intended to be displayed on screen. Example of a buffer 800x480 attached to + * layer for which we want to read and display on screen only a portion 320x240 taken in the center + * of the buffer. + * The pitch in pixels will be in that case 800 pixels and not 320 pixels as initially configured by + * previous call to HAL_LTDC_ConfigLayer(). + * @note This function should be called only after a previous call to HAL_LTDC_ConfigLayer() to modify the default + * pitch configured by HAL_LTDC_ConfigLayer() when required (refer to example described just above). + * Variant of the function HAL_LTDC_SetPitch without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LinePitchInPixels New line pitch in pixels to configure for LTDC layer 'LayerIdx'. + * @param LayerIdx LTDC layer index concerned by the modification of line pitch. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_SetPitch_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx) +{ + uint32_t tmp; + uint32_t pitchUpdate; + uint32_t pixelFormat; + + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* get LayerIdx used pixel format */ + pixelFormat = hltdc->LayerCfg[LayerIdx].PixelFormat; + + if (pixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) + { + tmp = 4U; + } + else if (pixelFormat == LTDC_PIXEL_FORMAT_RGB888) + { + tmp = 3U; + } + else if ((pixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \ + (pixelFormat == LTDC_PIXEL_FORMAT_AL88)) + { + tmp = 2U; + } + else + { + tmp = 1U; + } + + pitchUpdate = ((LinePitchInPixels * tmp) << 16U); + + /* Clear previously set standard pitch */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~LTDC_LxCFBLR_CFBP; + + /* Set new line pitch value */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLR |= pitchUpdate; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + + +/** + * @brief Configure the color keying without reloading. + * Variant of the function HAL_LTDC_ConfigColorKeying without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param RGBValue the color key value + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Configure the default color values */ + LTDC_LAYER(hltdc, LayerIdx)->CKCR &= ~(LTDC_LxCKCR_CKBLUE | LTDC_LxCKCR_CKGREEN | LTDC_LxCKCR_CKRED); + LTDC_LAYER(hltdc, LayerIdx)->CKCR = RGBValue; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Enable the color keying without reloading. + * Variant of the function HAL_LTDC_EnableColorKeying without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_EnableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Enable LTDC color keying by setting COLKEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_COLKEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Disable the color keying without reloading. + * Variant of the function HAL_LTDC_DisableColorKeying without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_DisableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable LTDC color keying by setting COLKEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_COLKEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Enable the color lookup table without reloading. + * Variant of the function HAL_LTDC_EnableCLUT without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_EnableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable LTDC color lookup table by setting CLUTEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_CLUTEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @brief Disable the color lookup table without reloading. + * Variant of the function HAL_LTDC_DisableCLUT without immediate reload. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: + * LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDC_DisableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LTDC_LAYER(LayerIdx)); + + /* Process locked */ + __HAL_LOCK(hltdc); + + /* Change LTDC peripheral state */ + hltdc->State = HAL_LTDC_STATE_BUSY; + + /* Disable LTDC color lookup table by setting CLUTEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR &= ~(uint32_t)LTDC_LxCR_CLUTEN; + + /* Change the LTDC state*/ + hltdc->State = HAL_LTDC_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hltdc); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup LTDC_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Check the LTDC handle state. + (+) Get the LTDC handle error code. + +@endverbatim + * @{ + */ + +/** + * @brief Return the LTDC handle state. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval HAL state + */ +HAL_LTDC_StateTypeDef HAL_LTDC_GetState(LTDC_HandleTypeDef *hltdc) +{ + return hltdc->State; +} + +/** + * @brief Return the LTDC handle error code. + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @retval LTDC Error Code + */ +uint32_t HAL_LTDC_GetError(LTDC_HandleTypeDef *hltdc) +{ + return hltdc->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup LTDC_Private_Functions LTDC Private Functions + * @{ + */ + +/** + * @brief Configure the LTDC peripheral + * @param hltdc Pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param pLayerCfg Pointer LTDC Layer Configuration structure + * @param LayerIdx LTDC Layer index. + * This parameter can be one of the following values: LTDC_LAYER_1 (0) or LTDC_LAYER_2 (1) + * @retval None + */ +static void LTDC_SetConfig(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx) +{ + uint32_t tmp; + uint32_t tmp1; + uint32_t tmp2; + + /* Configure the horizontal start and stop position */ + tmp = ((pLayerCfg->WindowX1 + ((hltdc->Instance->BPCR & LTDC_BPCR_AHBP) >> 16U)) << 16U); + LTDC_LAYER(hltdc, LayerIdx)->WHPCR &= ~(LTDC_LxWHPCR_WHSTPOS | LTDC_LxWHPCR_WHSPPOS); + LTDC_LAYER(hltdc, LayerIdx)->WHPCR = ((pLayerCfg->WindowX0 + \ + ((hltdc->Instance->BPCR & LTDC_BPCR_AHBP) >> 16U) + 1U) | tmp); + + /* Configure the vertical start and stop position */ + tmp = ((pLayerCfg->WindowY1 + (hltdc->Instance->BPCR & LTDC_BPCR_AVBP)) << 16U); + LTDC_LAYER(hltdc, LayerIdx)->WVPCR &= ~(LTDC_LxWVPCR_WVSTPOS | LTDC_LxWVPCR_WVSPPOS); + LTDC_LAYER(hltdc, LayerIdx)->WVPCR = ((pLayerCfg->WindowY0 + (hltdc->Instance->BPCR & LTDC_BPCR_AVBP) + 1U) | tmp); + + /* Specifies the pixel format */ + LTDC_LAYER(hltdc, LayerIdx)->PFCR &= ~(LTDC_LxPFCR_PF); + LTDC_LAYER(hltdc, LayerIdx)->PFCR = (pLayerCfg->PixelFormat); + + /* Configure the default color values */ + tmp = ((uint32_t)(pLayerCfg->Backcolor.Green) << 8U); + tmp1 = ((uint32_t)(pLayerCfg->Backcolor.Red) << 16U); + tmp2 = (pLayerCfg->Alpha0 << 24U); + LTDC_LAYER(hltdc, LayerIdx)->DCCR &= ~(LTDC_LxDCCR_DCBLUE | LTDC_LxDCCR_DCGREEN | LTDC_LxDCCR_DCRED | + LTDC_LxDCCR_DCALPHA); + LTDC_LAYER(hltdc, LayerIdx)->DCCR = (pLayerCfg->Backcolor.Blue | tmp | tmp1 | tmp2); + + /* Specifies the constant alpha value */ + LTDC_LAYER(hltdc, LayerIdx)->CACR &= ~(LTDC_LxCACR_CONSTA); + LTDC_LAYER(hltdc, LayerIdx)->CACR = (pLayerCfg->Alpha); + + /* Specifies the blending factors */ + LTDC_LAYER(hltdc, LayerIdx)->BFCR &= ~(LTDC_LxBFCR_BF2 | LTDC_LxBFCR_BF1); + LTDC_LAYER(hltdc, LayerIdx)->BFCR = (pLayerCfg->BlendingFactor1 | pLayerCfg->BlendingFactor2); + + /* Configure the color frame buffer start address */ + LTDC_LAYER(hltdc, LayerIdx)->CFBAR &= ~(LTDC_LxCFBAR_CFBADD); + LTDC_LAYER(hltdc, LayerIdx)->CFBAR = (pLayerCfg->FBStartAdress); + + if (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB8888) + { + tmp = 4U; + } + else if (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_RGB888) + { + tmp = 3U; + } + else if ((pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB4444) || \ + (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_RGB565) || \ + (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_ARGB1555) || \ + (pLayerCfg->PixelFormat == LTDC_PIXEL_FORMAT_AL88)) + { + tmp = 2U; + } + else + { + tmp = 1U; + } + + /* Configure the color frame buffer pitch in byte */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLR &= ~(LTDC_LxCFBLR_CFBLL | LTDC_LxCFBLR_CFBP); + LTDC_LAYER(hltdc, LayerIdx)->CFBLR = (((pLayerCfg->ImageWidth * tmp) << 16U) | \ + (((pLayerCfg->WindowX1 - pLayerCfg->WindowX0) * tmp) + 3U)); + /* Configure the frame buffer line number */ + LTDC_LAYER(hltdc, LayerIdx)->CFBLNR &= ~(LTDC_LxCFBLNR_CFBLNBR); + LTDC_LAYER(hltdc, LayerIdx)->CFBLNR = (pLayerCfg->ImageHeight); + + /* Enable LTDC_Layer by setting LEN bit */ + LTDC_LAYER(hltdc, LayerIdx)->CR |= (uint32_t)LTDC_LxCR_LEN; +} + +/** + * @} + */ + + +/** + * @} + */ + +#endif /* LTDC */ + +#endif /* HAL_LTDC_MODULE_ENABLED */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c new file mode 100644 index 0000000..2ee7795 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_ltdc_ex.c @@ -0,0 +1,151 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_ltdc_ex.c + * @author MCD Application Team + * @brief LTDC Extension HAL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#if defined(HAL_LTDC_MODULE_ENABLED) && defined(HAL_DSI_MODULE_ENABLED) + +#if defined (LTDC) && defined (DSI) + +/** @defgroup LTDCEx LTDCEx + * @brief LTDC HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup LTDCEx_Exported_Functions LTDC Extended Exported Functions + * @{ + */ + +/** @defgroup LTDCEx_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Initialize and configure the LTDC + +@endverbatim + * @{ + */ + +/** + * @brief Retrieve common parameters from DSI Video mode configuration structure + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param VidCfg pointer to a DSI_VidCfgTypeDef structure that contains + * the DSI video mode configuration parameters + * @note The implementation of this function is taking into account the LTDC + * polarities inversion as described in the current LTDC specification + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDCEx_StructInitFromVideoConfig(LTDC_HandleTypeDef *hltdc, DSI_VidCfgTypeDef *VidCfg) +{ + /* Retrieve signal polarities from DSI */ + + /* The following polarity is inverted: + LTDC_DEPOLARITY_AL <-> LTDC_DEPOLARITY_AH */ + + /* Note 1 : Code in line w/ Current LTDC specification */ + hltdc->Init.DEPolarity = (VidCfg->DEPolarity == \ + DSI_DATA_ENABLE_ACTIVE_HIGH) ? LTDC_DEPOLARITY_AL : LTDC_DEPOLARITY_AH; + hltdc->Init.VSPolarity = (VidCfg->VSPolarity == DSI_VSYNC_ACTIVE_HIGH) ? LTDC_VSPOLARITY_AH : LTDC_VSPOLARITY_AL; + hltdc->Init.HSPolarity = (VidCfg->HSPolarity == DSI_HSYNC_ACTIVE_HIGH) ? LTDC_HSPOLARITY_AH : LTDC_HSPOLARITY_AL; + + /* Note 2: Code to be used in case LTDC polarities inversion updated in the specification */ + /* hltdc->Init.DEPolarity = VidCfg->DEPolarity << 29; + hltdc->Init.VSPolarity = VidCfg->VSPolarity << 29; + hltdc->Init.HSPolarity = VidCfg->HSPolarity << 29; */ + + /* Retrieve vertical timing parameters from DSI */ + hltdc->Init.VerticalSync = VidCfg->VerticalSyncActive - 1U; + hltdc->Init.AccumulatedVBP = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch - 1U; + hltdc->Init.AccumulatedActiveH = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch + \ + VidCfg->VerticalActive - 1U; + hltdc->Init.TotalHeigh = VidCfg->VerticalSyncActive + VidCfg->VerticalBackPorch + \ + VidCfg->VerticalActive + VidCfg->VerticalFrontPorch - 1U; + + return HAL_OK; +} + +/** + * @brief Retrieve common parameters from DSI Adapted command mode configuration structure + * @param hltdc pointer to a LTDC_HandleTypeDef structure that contains + * the configuration information for the LTDC. + * @param CmdCfg pointer to a DSI_CmdCfgTypeDef structure that contains + * the DSI command mode configuration parameters + * @note The implementation of this function is taking into account the LTDC + * polarities inversion as described in the current LTDC specification + * @retval HAL status + */ +HAL_StatusTypeDef HAL_LTDCEx_StructInitFromAdaptedCommandConfig(LTDC_HandleTypeDef *hltdc, DSI_CmdCfgTypeDef *CmdCfg) +{ + /* Retrieve signal polarities from DSI */ + + /* The following polarities are inverted: + LTDC_DEPOLARITY_AL <-> LTDC_DEPOLARITY_AH + LTDC_VSPOLARITY_AL <-> LTDC_VSPOLARITY_AH + LTDC_HSPOLARITY_AL <-> LTDC_HSPOLARITY_AH)*/ + + /* Note 1 : Code in line w/ Current LTDC specification */ + hltdc->Init.DEPolarity = (CmdCfg->DEPolarity == \ + DSI_DATA_ENABLE_ACTIVE_HIGH) ? LTDC_DEPOLARITY_AL : LTDC_DEPOLARITY_AH; + hltdc->Init.VSPolarity = (CmdCfg->VSPolarity == DSI_VSYNC_ACTIVE_HIGH) ? LTDC_VSPOLARITY_AL : LTDC_VSPOLARITY_AH; + hltdc->Init.HSPolarity = (CmdCfg->HSPolarity == DSI_HSYNC_ACTIVE_HIGH) ? LTDC_HSPOLARITY_AL : LTDC_HSPOLARITY_AH; + + /* Note 2: Code to be used in case LTDC polarities inversion updated in the specification */ + /* hltdc->Init.DEPolarity = CmdCfg->DEPolarity << 29; + hltdc->Init.VSPolarity = CmdCfg->VSPolarity << 29; + hltdc->Init.HSPolarity = CmdCfg->HSPolarity << 29; */ + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* LTDC && DSI */ + +#endif /* HAL_LTCD_MODULE_ENABLED && HAL_DSI_MODULE_ENABLED */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c new file mode 100644 index 0000000..466eab5 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_mmc.c @@ -0,0 +1,3201 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_mmc.c + * @author MCD Application Team + * @brief MMC card HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Secure Digital (MMC) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + MMC card Control 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 ##### + ============================================================================== + [..] + This driver implements a high level communication layer for read and write from/to + this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by + the user in HAL_MMC_MspInit() function (MSP layer). + Basically, the MSP layer configuration should be the same as we provide in the + examples. + You can easily tailor this configuration according to hardware resources. + + [..] + This driver is a generic layered driver for SDMMC memories which uses the HAL + SDMMC driver functions to interface with MMC and eMMC cards devices. + It is used as follows: + + (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API: + (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE(); + (##) SDMMC pins configuration for MMC card + (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init() + and according to your pin assignment; + (##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA() + and HAL_MMC_WriteBlocks_DMA() APIs). + (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE(); + (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled. + (##) NVIC configuration if you need to use interrupt process when using DMA transfer. + (+++) Configure the SDMMC and DMA interrupt priorities using function HAL_NVIC_SetPriority(); + DMA priority is superior to SDMMC's priority + (+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ() + (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT() + and __HAL_MMC_DISABLE_IT() inside the communication process. + (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT() + and __HAL_MMC_CLEAR_IT() + (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT() + and HAL_MMC_WriteBlocks_IT() APIs). + (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority(); + (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ() + (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT() + and __HAL_MMC_DISABLE_IT() inside the communication process. + (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT() + and __HAL_MMC_CLEAR_IT() + (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization + + + *** MMC Card Initialization and configuration *** + ================================================ + [..] + To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes + SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer). + This function provide the following operations: + + (#) Initialize the SDMMC peripheral interface with default configuration. + The initialization process is done at 400KHz. You can change or adapt + this frequency by adjusting the "ClockDiv" field. + The MMC Card frequency (SDMMC_CK) is computed as follows: + + SDMMC_CK = SDMMCCLK / (ClockDiv + 2) + + In initialization mode and according to the MMC Card standard, + make sure that the SDMMC_CK frequency doesn't exceed 400KHz. + + This phase of initialization is done through SDMMC_Init() and + SDMMC_PowerState_ON() SDMMC low level APIs. + + (#) Initialize the MMC card. The API used is HAL_MMC_InitCard(). + This phase allows the card initialization and identification + and check the MMC Card type (Standard Capacity or High Capacity) + The initialization flow is compatible with MMC standard. + + This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case + of plug-off plug-in. + + (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer + frequency is set to 24MHz. You can change or adapt this frequency by adjusting + the "ClockDiv" field. + In transfer mode and according to the MMC Card standard, make sure that the + SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch. + To be able to use a frequency higher than 24MHz, you should use the SDMMC + peripheral in bypass mode. Refer to the corresponding reference manual + for more details. + + (#) Select the corresponding MMC Card according to the address read with the step 2. + + (#) Configure the MMC Card in wide bus mode: 4-bits data. + + *** MMC Card Read operation *** + ============================== + [..] + (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + + (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + You could also check the DMA transfer process through the MMC Rx interrupt event. + + (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT(). + This function allows the read of 512 bytes blocks. + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + You could also check the IT transfer process through the MMC Rx interrupt event. + + *** MMC Card Write operation *** + =============================== + [..] + (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + + (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA(). + This function support only 512-bytes block length (the block size should be + chosen as 512 byte). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + You could also check the DMA transfer process through the MMC Tx interrupt event. + + (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT(). + This function allows the read of 512 bytes blocks. + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_MMC_GetCardState() function for MMC card state. + You could also check the IT transfer process through the MMC Tx interrupt event. + + *** MMC card information *** + =========================== + [..] + (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo(). + It returns useful information about the MMC card such as block size, card type, + block number ... + + *** MMC card CSD register *** + ============================ + [..] + (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register. + Some of the CSD parameters are useful for card initialization and identification. + + *** MMC card CID register *** + ============================ + [..] + (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register. + Some of the CID parameters are useful for card initialization and identification. + + *** MMC HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in MMC HAL driver. + + (+) __HAL_MMC_ENABLE : Enable the MMC device + (+) __HAL_MMC_DISABLE : Disable the MMC device + (+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer + (+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer + (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt + (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt + (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not + (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags + + [..] + (@) You can refer to the MMC HAL driver header file for more useful macros + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_MMC_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) MspInitCallback : MMC MspInit. + (+) MspDeInitCallback : MMC MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) MspInitCallback : MMC MspInit. + (+) MspDeInitCallback : MMC MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_MMC_Init + and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_MMC_RegisterCallback before calling HAL_MMC_DeInit + or HAL_MMC_Init function. + + When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup MMC MMC + * @brief MMC HAL module driver + * @{ + */ + +#ifdef HAL_MMC_MODULE_ENABLED + +#if defined(SDIO) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup MMC_Private_Defines + * @{ + */ +#if defined (VDD_VALUE) && (VDD_VALUE <= 1950U) +#define MMC_VOLTAGE_RANGE EMMC_LOW_VOLTAGE_RANGE + +#define MMC_EXT_CSD_PWR_CL_26_INDEX 201 +#define MMC_EXT_CSD_PWR_CL_52_INDEX 200 +#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238 + +#define MMC_EXT_CSD_PWR_CL_26_POS 8 +#define MMC_EXT_CSD_PWR_CL_52_POS 0 +#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 16 +#else +#define MMC_VOLTAGE_RANGE EMMC_HIGH_VOLTAGE_RANGE + +#define MMC_EXT_CSD_PWR_CL_26_INDEX 203 +#define MMC_EXT_CSD_PWR_CL_52_INDEX 202 +#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239 + +#define MMC_EXT_CSD_PWR_CL_26_POS 24 +#define MMC_EXT_CSD_PWR_CL_52_POS 16 +#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 24 +#endif + +/* Frequencies used in the driver for clock divider calculation */ +#define MMC_INIT_FREQ 400000U /* Initialization phase : 400 kHz max */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup MMC_Private_Functions MMC Private Functions + * @{ + */ +static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc); +static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc); +static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus); +static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout); +static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc); +static void MMC_Write_IT(MMC_HandleTypeDef *hmmc); +static void MMC_Read_IT(MMC_HandleTypeDef *hmmc); +static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void MMC_DMAError(DMA_HandleTypeDef *hdma); +static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma); +static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma); +static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide); +/** + * @} + */ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup MMC_Exported_Functions + * @{ + */ + +/** @addtogroup MMC_Exported_Functions_Group1 + * @brief Initialization and de-initialization functions + * +@verbatim + ============================================================================== + ##### Initialization and de-initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize the MMC + card device to be ready for use. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the MMC according to the specified parameters in the + MMC_HandleTypeDef and create the associated handle. + * @param hmmc: Pointer to the MMC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc) +{ + /* Check the MMC handle allocation */ + if(hmmc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance)); + assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge)); + assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass)); + assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave)); + assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide)); + assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl)); + assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv)); + + if(hmmc->State == HAL_MMC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hmmc->Lock = HAL_UNLOCKED; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + /* Reset Callback pointers in HAL_MMC_STATE_RESET only */ + hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback; + hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback; + hmmc->ErrorCallback = HAL_MMC_ErrorCallback; + hmmc->AbortCpltCallback = HAL_MMC_AbortCallback; + + if(hmmc->MspInitCallback == NULL) + { + hmmc->MspInitCallback = HAL_MMC_MspInit; + } + + /* Init the low level hardware */ + hmmc->MspInitCallback(hmmc); +#else + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_MMC_MspInit(hmmc); +#endif + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize the Card parameters */ + if(HAL_MMC_InitCard(hmmc) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* Initialize the error code */ + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + /* Initialize the MMC operation */ + hmmc->Context = MMC_CONTEXT_NONE; + + /* Initialize the MMC state */ + hmmc->State = HAL_MMC_STATE_READY; + + /* Configure bus width */ + if (hmmc->Init.BusWide != SDIO_BUS_WIDE_1B) + { + if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK) + { + return HAL_ERROR; + } + } + + return HAL_OK; +} + +/** + * @brief Initializes the MMC Card. + * @param hmmc: Pointer to MMC handle + * @note This function initializes the MMC card. It could be used when a card + re-initialization is needed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc) +{ + uint32_t errorstate; + MMC_InitTypeDef Init; + HAL_StatusTypeDef status; + + /* Default SDIO peripheral configuration for MMC card initialization */ + Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + Init.BusWide = SDIO_BUS_WIDE_1B; + Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + Init.ClockDiv = SDIO_INIT_CLK_DIV; + + /* Initialize SDIO peripheral interface with default configuration */ + status = SDIO_Init(hmmc->Instance, Init); + if(status == HAL_ERROR) + { + return HAL_ERROR; + } + + /* Disable SDIO Clock */ + __HAL_MMC_DISABLE(hmmc); + + /* Set Power State to ON */ + status = SDIO_PowerState_ON(hmmc->Instance); + if(status == HAL_ERROR) + { + return HAL_ERROR; + } + + /* Enable MMC Clock */ + __HAL_MMC_ENABLE(hmmc); + + /* Required power up waiting time before starting the MMC initialization sequence */ + HAL_Delay(2); + + /* Identify card operating voltage */ + errorstate = MMC_PowerON(hmmc); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->State = HAL_MMC_STATE_READY; + hmmc->ErrorCode |= errorstate; + return HAL_ERROR; + } + + /* Card initialization */ + errorstate = MMC_InitCard(hmmc); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->State = HAL_MMC_STATE_READY; + hmmc->ErrorCode |= errorstate; + return HAL_ERROR; + } + + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief De-Initializes the MMC card. + * @param hmmc: Pointer to MMC handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc) +{ + /* Check the MMC handle allocation */ + if(hmmc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance)); + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Set MMC power state to off */ + MMC_PowerOFF(hmmc); + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + if(hmmc->MspDeInitCallback == NULL) + { + hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; + } + + /* DeInit the low level hardware */ + hmmc->MspDeInitCallback(hmmc); +#else + /* De-Initialize the MSP layer */ + HAL_MMC_MspDeInit(hmmc); +#endif + + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + hmmc->State = HAL_MMC_STATE_RESET; + + return HAL_OK; +} + + +/** + * @brief Initializes the MMC MSP. + * @param hmmc: Pointer to MMC handle + * @retval None + */ +__weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_MMC_MspInit could be implemented in the user file + */ +} + +/** + * @brief De-Initialize MMC MSP. + * @param hmmc: Pointer to MMC handle + * @retval None + */ +__weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_MMC_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @addtogroup MMC_Exported_Functions_Group2 + * @brief Data transfer functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the data + transfer from/to MMC card. + +@endverbatim + * @{ + */ + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed by polling mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @param hmmc: Pointer to MMC handle + * @param pData: pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of MMC blocks to read + * @param Timeout: Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count, data, dataremaining; + uint32_t add = BlockAdd; + uint8_t *tempbuff = pData; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Read block(s) in polling mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK; + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK; + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); + } + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Poll on SDIO flags */ + dataremaining = config.DataLength; +#if defined(SDIO_STA_STBITERR) + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) +#else /* SDIO_STA_STBITERR not defined */ + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) +#endif /* SDIO_STA_STBITERR */ + { + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U)) + { + /* Read data from SDIO Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = SDIO_ReadFIFO(hmmc->Instance); + *tempbuff = (uint8_t)(data & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 8U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 16U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 24U) & 0xFFU); + tempbuff++; + dataremaining--; + } + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; + hmmc->State= HAL_MMC_STATE_READY; + return HAL_TIMEOUT; + } + } + + /* Send stop transmission command in case of multiblock read */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U)) + { + /* Send stop transmission command */ + errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + } + + /* Get error state */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else + { + /* Nothing to do */ + } + + /* Empty FIFO if there is still any data */ + while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U)) + { + data = SDIO_ReadFIFO(hmmc->Instance); + *tempbuff = (uint8_t)(data & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 8U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 16U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 24U) & 0xFFU); + tempbuff++; + dataremaining--; + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; + hmmc->State= HAL_MMC_STATE_READY; + return HAL_ERROR; + } + } + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + hmmc->State = HAL_MMC_STATE_READY; + + return HAL_OK; + } + else + { + hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY; + return HAL_ERROR; + } +} + +/** + * @brief Allows to write block(s) to a specified address in a card. The Data + * transfer is managed by polling mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @param hmmc: Pointer to MMC handle + * @param pData: pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of MMC blocks to write + * @param Timeout: Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count, data, dataremaining; + uint32_t add = BlockAdd; + uint8_t *tempbuff = pData; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK; + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK; + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); + } + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Write block(s) in polling mode */ + dataremaining = config.DataLength; +#if defined(SDIO_STA_STBITERR) + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) +#else /* SDIO_STA_STBITERR not defined */ + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) +#endif /* SDIO_STA_STBITERR */ + { + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U)) + { + /* Write data to SDIO Tx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = (uint32_t)(*tempbuff); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 8U); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 16U); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 24U); + tempbuff++; + dataremaining--; + (void)SDIO_WriteFIFO(hmmc->Instance, &data); + } + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_TIMEOUT; + } + } + + /* Send stop transmission command in case of multiblock write */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U)) + { + /* Send stop transmission command */ + errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + } + + /* Get error state */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else + { + /* Nothing to do */ + } + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + hmmc->State = HAL_MMC_STATE_READY; + + return HAL_OK; + } + else + { + hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY; + return HAL_ERROR; + } +} + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed in interrupt mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @note You could also check the IT transfer process through the MMC Rx + * interrupt event. + * @param hmmc: Pointer to MMC handle + * @param pData: Pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of blocks to read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + + hmmc->pRxBuffPtr = pData; + hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; + +#if defined(SDIO_STA_STBITERR) + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF)); +#endif /* SDIO_STA_STBITERR */ + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Read Blocks in IT mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT); + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT); + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); + } + + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Writes block(s) to a specified address in a card. The Data transfer + * is managed in interrupt mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @note You could also check the IT transfer process through the MMC Tx + * interrupt event. + * @param hmmc: Pointer to MMC handle + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of blocks to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + + hmmc->pTxBuffPtr = pData; + hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; + + /* Enable transfer interrupts */ +#if defined(SDIO_STA_STBITERR) + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE)); +#endif /* SDIO_STA_STBITERR */ + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT); + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT); + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); + } + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed by DMA mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @note You could also check the DMA transfer process through the MMC Rx + * interrupt event. + * @param hmmc: Pointer MMC handle + * @param pData: Pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of blocks to read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + +#if defined(SDIO_STA_STBITERR) + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); +#endif /* SDIO_STA_STBITERR */ + + /* Set the DMA transfer complete callback */ + hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt; + + /* Set the DMA error callback */ + hmmc->hdmarx->XferErrorCallback = MMC_DMAError; + + /* Set the DMA Abort callback */ + hmmc->hdmarx->XferAbortCallback = NULL; + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + /* Force DMA Direction */ + hmmc->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY; + MODIFY_REG(hmmc->hdmarx->Instance->CR, DMA_SxCR_DIR, hmmc->hdmarx->Init.Direction); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK) + { + __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode = HAL_MMC_ERROR_DMA; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else + { + /* Enable MMC DMA transfer */ + __HAL_MMC_DMA_ENABLE(hmmc); + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Read Blocks in DMA mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA); + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); + } + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); + hmmc->ErrorCode = errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + return HAL_OK; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Writes block(s) to a specified address in a card. The Data transfer + * is managed by DMA mode. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @note You could also check the DMA transfer process through the MMC Tx + * interrupt event. + * @param hmmc: Pointer to MMC handle + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of blocks to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0U; + + /* Enable MMC Error interrupts */ +#if defined(SDIO_STA_STBITERR) + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); +#endif /* SDIO_STA_STBITERR */ + + /* Set the DMA transfer complete callback */ + hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt; + + /* Set the DMA error callback */ + hmmc->hdmatx->XferErrorCallback = MMC_DMAError; + + /* Set the DMA Abort callback */ + hmmc->hdmatx->XferAbortCallback = NULL; + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + add *= 512U; + } + + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); + } + else + { + hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA); + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); + } + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Enable SDIO DMA transfer */ + __HAL_MMC_DMA_ENABLE(hmmc); + + /* Force DMA Direction */ + hmmc->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH; + MODIFY_REG(hmmc->hdmatx->Instance->CR, DMA_SxCR_DIR, hmmc->hdmatx->Init.Direction); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK) + { + __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND)); + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DMA; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else + { + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + return HAL_OK; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Erases the specified memory area of the given MMC card. + * @note This API should be followed by a check on the card state through + * HAL_MMC_GetCardState(). + * @param hmmc: Pointer to MMC handle + * @param BlockStartAdd: Start Block address + * @param BlockEndAdd: End Block address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd) +{ + uint32_t errorstate; + uint32_t start_add = BlockStartAdd; + uint32_t end_add = BlockEndAdd; + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + if(end_add < start_add) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(end_add > (hmmc->MmcCard.LogBlockNbr)) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Check if the card command class supports erase command */ + if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) + { + start_add *= 512U; + end_add *= 512U; + } + + /* Send CMD35 MMC_ERASE_GRP_START with argument as addr */ + errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Send CMD36 MMC_ERASE_GRP_END with argument as addr */ + errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Send CMD38 ERASE */ + errorstate = SDMMC_CmdErase(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + hmmc->State = HAL_MMC_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief This function handles MMC card interrupt request. + * @param hmmc: Pointer to MMC handle + * @retval None + */ +void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc) +{ + uint32_t errorstate; + uint32_t context = hmmc->Context; + + /* Check for SDIO interrupt flags */ + if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U)) + { + MMC_Read_IT(hmmc); + } + + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) != RESET) + { + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND); + +#if defined(SDIO_STA_STBITERR) + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT |\ + SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_TXFIFOHE |\ + SDIO_IT_RXFIFOHF); +#endif /* SDIO_STA_STBITERR */ + + hmmc->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN); + + if((context & MMC_CONTEXT_DMA) != 0U) + { + if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U) + { + errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } + } + if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) + { + /* Disable the DMA transfer for transmit request by setting the DMAEN bit + in the MMC DCTRL register */ + hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + hmmc->State = HAL_MMC_STATE_READY; + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->TxCpltCallback(hmmc); +#else + HAL_MMC_TxCpltCallback(hmmc); +#endif + } + } + else if((context & MMC_CONTEXT_IT) != 0U) + { + /* Stop Transfer for Write Multi blocks or Read Multi blocks */ + if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) + { + errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } + } + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + hmmc->State = HAL_MMC_STATE_READY; + if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->RxCpltCallback(hmmc); +#else + HAL_MMC_RxCpltCallback(hmmc); +#endif + } + else + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->TxCpltCallback(hmmc); +#else + HAL_MMC_TxCpltCallback(hmmc); +#endif + } + } + else + { + /* Nothing to do */ + } + } + + else if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U)) + { + MMC_Write_IT(hmmc); + } + +#if defined(SDIO_STA_STBITERR) + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR | SDIO_FLAG_STBITERR) != RESET) +#else /* SDIO_STA_STBITERR not defined */ + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET) +#endif /* SDIO_STA_STBITERR */ + { + /* Set Error code */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL) != RESET) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; + } + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT) != RESET) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; + } + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR) != RESET) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; + } + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR) != RESET) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; + } +#if defined(SDIO_STA_STBITERR) + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_STBITERR) != RESET) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; + } +#endif /* SDIO_STA_STBITERR */ + +#if defined(SDIO_STA_STBITERR) + /* Clear All flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR); + + /* Disable all interrupts */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR); +#else /* SDIO_STA_STBITERR */ + /* Clear All flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + /* Disable all interrupts */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); +#endif /* SDIO_STA_STBITERR */ + + hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance); + + if((context & MMC_CONTEXT_IT) != 0U) + { + /* Set the MMC state to ready to be able to start again the process */ + hmmc->State = HAL_MMC_STATE_READY; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ + } + else if((context & MMC_CONTEXT_DMA) != 0U) + { + /* Abort the MMC DMA Streams */ + if(hmmc->hdmatx != NULL) + { + /* Set the DMA Tx abort callback */ + hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort; + /* Abort DMA in IT mode */ + if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK) + { + MMC_DMATxAbort(hmmc->hdmatx); + } + } + else if(hmmc->hdmarx != NULL) + { + /* Set the DMA Rx abort callback */ + hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort; + /* Abort DMA in IT mode */ + if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK) + { + MMC_DMARxAbort(hmmc->hdmarx); + } + } + else + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + hmmc->State = HAL_MMC_STATE_READY; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->AbortCpltCallback(hmmc); +#else + HAL_MMC_AbortCallback(hmmc); +#endif + } + } + else + { + /* Nothing to do */ + } + } + + else + { + /* Nothing to do */ + } +} + +/** + * @brief return the MMC state + * @param hmmc: Pointer to mmc handle + * @retval HAL state + */ +HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc) +{ + return hmmc->State; +} + +/** +* @brief Return the MMC error code +* @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains + * the configuration information. +* @retval MMC Error Code +*/ +uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc) +{ + return hmmc->ErrorCode; +} + +/** + * @brief Tx Transfer completed callbacks + * @param hmmc: Pointer to MMC handle + * @retval None + */ +__weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MMC_TxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks + * @param hmmc: Pointer MMC handle + * @retval None + */ +__weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MMC_RxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief MMC error callbacks + * @param hmmc: Pointer MMC handle + * @retval None + */ +__weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MMC_ErrorCallback can be implemented in the user file + */ +} + +/** + * @brief MMC Abort callbacks + * @param hmmc: Pointer MMC handle + * @retval None + */ +__weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hmmc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_MMC_AbortCallback can be implemented in the user file + */ +} + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User MMC Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hmmc : MMC handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID + * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID + * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID + * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID + * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID + * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hmmc); + + if(hmmc->State == HAL_MMC_STATE_READY) + { + switch (CallbackId) + { + case HAL_MMC_TX_CPLT_CB_ID : + hmmc->TxCpltCallback = pCallback; + break; + case HAL_MMC_RX_CPLT_CB_ID : + hmmc->RxCpltCallback = pCallback; + break; + case HAL_MMC_ERROR_CB_ID : + hmmc->ErrorCallback = pCallback; + break; + case HAL_MMC_ABORT_CB_ID : + hmmc->AbortCpltCallback = pCallback; + break; + case HAL_MMC_MSP_INIT_CB_ID : + hmmc->MspInitCallback = pCallback; + break; + case HAL_MMC_MSP_DEINIT_CB_ID : + hmmc->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hmmc->State == HAL_MMC_STATE_RESET) + { + switch (CallbackId) + { + case HAL_MMC_MSP_INIT_CB_ID : + hmmc->MspInitCallback = pCallback; + break; + case HAL_MMC_MSP_DEINIT_CB_ID : + hmmc->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hmmc); + return status; +} + +/** + * @brief Unregister a User MMC Callback + * MMC Callback is redirected to the weak (surcharged) predefined callback + * @param hmmc : MMC handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID + * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID + * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID + * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID + * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID + * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hmmc); + + if(hmmc->State == HAL_MMC_STATE_READY) + { + switch (CallbackId) + { + case HAL_MMC_TX_CPLT_CB_ID : + hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback; + break; + case HAL_MMC_RX_CPLT_CB_ID : + hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback; + break; + case HAL_MMC_ERROR_CB_ID : + hmmc->ErrorCallback = HAL_MMC_ErrorCallback; + break; + case HAL_MMC_ABORT_CB_ID : + hmmc->AbortCpltCallback = HAL_MMC_AbortCallback; + break; + case HAL_MMC_MSP_INIT_CB_ID : + hmmc->MspInitCallback = HAL_MMC_MspInit; + break; + case HAL_MMC_MSP_DEINIT_CB_ID : + hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; + break; + default : + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hmmc->State == HAL_MMC_STATE_RESET) + { + switch (CallbackId) + { + case HAL_MMC_MSP_INIT_CB_ID : + hmmc->MspInitCallback = HAL_MMC_MspInit; + break; + case HAL_MMC_MSP_DEINIT_CB_ID : + hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; + break; + default : + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hmmc); + return status; +} +#endif + +/** + * @} + */ + +/** @addtogroup MMC_Exported_Functions_Group3 + * @brief management functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the MMC card + operations and get the related information + +@endverbatim + * @{ + */ + +/** + * @brief Returns information the information of the card which are stored on + * the CID register. + * @param hmmc: Pointer to MMC handle + * @param pCID: Pointer to a HAL_MMC_CIDTypedef structure that + * contains all CID register parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID) +{ + pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U); + + pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U); + + pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U)); + + pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU); + + pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U); + + pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U)); + + pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U); + + pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U); + + pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U); + + pCID->Reserved2 = 1U; + + return HAL_OK; +} + +/** + * @brief Returns information the information of the card which are stored on + * the CSD register. + * @param hmmc: Pointer to MMC handle + * @param pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that + * contains all CSD register parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD) +{ + uint32_t block_nbr = 0; + + pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U); + + pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U); + + pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U); + + pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U); + + pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U); + + pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU); + + pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U); + + pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U); + + pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U); + + pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U); + + pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U); + + pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U); + + pCSD->Reserved2 = 0U; /*!< Reserved */ + + pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U)); + + pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U); + + pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U); + + pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U); + + pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U); + + pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U); + + if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */ + { + return HAL_ERROR; + } + + if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD) + { + hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ; + hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U)); + hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU)); + hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U); + hmmc->MmcCard.LogBlockSize = 512U; + } + else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD) + { + hmmc->MmcCard.BlockNbr = block_nbr; + hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr; + hmmc->MmcCard.BlockSize = 512U; + hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize; + } + else + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U); + + pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U); + + pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU); + + pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U); + + pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U); + + pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U); + + pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U); + + pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U); + + pCSD->Reserved3 = 0; + + pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U); + + pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U); + + pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U); + + pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U); + + pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U); + + pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U); + + pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U); + + pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U); + + pCSD->Reserved4 = 1; + + return HAL_OK; +} + +/** + * @brief Gets the MMC card info. + * @param hmmc: Pointer to MMC handle + * @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that + * will contain the MMC card status information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo) +{ + pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType); + pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class); + pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd); + pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr); + pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize); + pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr); + pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize); + + return HAL_OK; +} + +/** + * @brief Returns information the information of the card which are stored on + * the Extended CSD register. + * @param hmmc Pointer to MMC handle + * @param pExtCSD Pointer to a memory area (512 bytes) that contains all + * Extended CSD register parameters + * @param Timeout Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count; + uint32_t *tmp_buf; + + if(NULL == pExtCSD) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; + return HAL_ERROR; + } + + if(hmmc->State == HAL_MMC_STATE_READY) + { + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + hmmc->State = HAL_MMC_STATE_BUSY; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0; + + /* Initiaize the destination pointer */ + tmp_buf = pExtCSD; + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = 512; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Send ExtCSD Read command to Card */ + errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Poll on SDMMC flags */ + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) + { + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF)) + { + /* Read data from SDMMC Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + *tmp_buf = SDIO_ReadFIFO(hmmc->Instance); + tmp_buf++; + } + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; + hmmc->State= HAL_MMC_STATE_READY; + return HAL_TIMEOUT; + } + } + + /* Get error state */ + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + else + { + /* Nothing to do */ + } + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + hmmc->State = HAL_MMC_STATE_READY; + } + + return HAL_OK; +} + +/** + * @brief Enables wide bus operation for the requested card if supported by + * card. + * @param hmmc: Pointer to MMC handle + * @param WideMode: Specifies the MMC card wide bus mode + * This parameter can be one of the following values: + * @arg SDIO_BUS_WIDE_8B: 8-bit data transfer + * @arg SDIO_BUS_WIDE_4B: 4-bit data transfer + * @arg SDIO_BUS_WIDE_1B: 1-bit data transfer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode) +{ + uint32_t count; + SDIO_InitTypeDef Init; + uint32_t errorstate; + uint32_t response = 0U; + + /* Check the parameters */ + assert_param(IS_SDIO_BUS_WIDE(WideMode)); + + /* Change State */ + hmmc->State = HAL_MMC_STATE_BUSY; + + errorstate = MMC_PwrClassUpdate(hmmc, WideMode); + + if(errorstate == HAL_MMC_ERROR_NONE) + { + if(WideMode == SDIO_BUS_WIDE_8B) + { + errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U); + } + else if(WideMode == SDIO_BUS_WIDE_4B) + { + errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U); + } + else if(WideMode == SDIO_BUS_WIDE_1B) + { + errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U); + } + else + { + /* WideMode is not a valid argument*/ + errorstate = HAL_MMC_ERROR_PARAM; + } + + /* Check for switch error and violation of the trial number of sending CMD 13 */ + if(errorstate == HAL_MMC_ERROR_NONE) + { + /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ + count = SDMMC_MAX_TRIAL; + do + { + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + break; + } + + /* Get command response */ + response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + count--; + }while(((response & 0x100U) == 0U) && (count != 0U)); + + /* Check the status after the switch command execution */ + if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) + { + /* Check the bit SWITCH_ERROR of the device status */ + if ((response & 0x80U) != 0U) + { + errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; + } + else + { + /* Configure the SDIO peripheral */ + Init = hmmc->Init; + Init.BusWide = WideMode; + (void)SDIO_Init(hmmc->Instance, Init); + } + } + else if (count == 0U) + { + errorstate = SDMMC_ERROR_TIMEOUT; + } + else + { + /* Nothing to do */ + } + } + } + + /* Change State */ + hmmc->State = HAL_MMC_STATE_READY; + + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Gets the current mmc card data state. + * @param hmmc: pointer to MMC handle + * @retval Card state + */ +HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc) +{ + uint32_t cardstate; + uint32_t errorstate; + uint32_t resp1 = 0U; + + errorstate = MMC_SendStatus(hmmc, &resp1); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; + } + + cardstate = ((resp1 >> 9U) & 0x0FU); + + return (HAL_MMC_CardStateTypeDef)cardstate; +} + +/** + * @brief Abort the current transfer and disable the MMC. + * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains + * the configuration information for MMC module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc) +{ + HAL_MMC_CardStateTypeDef CardState; + + /* DIsable All interrupts */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + /* Clear All flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL)) + { + /* Disable the MMC DMA request */ + hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Abort the MMC DMA Tx Stream */ + if(hmmc->hdmatx != NULL) + { + if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_DMA; + } + } + /* Abort the MMC DMA Rx Stream */ + if(hmmc->hdmarx != NULL) + { + if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK) + { + hmmc->ErrorCode |= HAL_MMC_ERROR_DMA; + } + } + } + + hmmc->State = HAL_MMC_STATE_READY; + + /* Initialize the MMC operation */ + hmmc->Context = MMC_CONTEXT_NONE; + + CardState = HAL_MMC_GetCardState(hmmc); + if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) + { + hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance); + } + if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE) + { + return HAL_ERROR; + } + return HAL_OK; +} + +/** + * @brief Abort the current transfer and disable the MMC (IT mode). + * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains + * the configuration information for MMC module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc) +{ + HAL_MMC_CardStateTypeDef CardState; + + /* DIsable All interrupts */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + /* Clear All flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL)) + { + /* Disable the MMC DMA request */ + hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Abort the MMC DMA Tx Stream */ + if(hmmc->hdmatx != NULL) + { + hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort; + if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK) + { + hmmc->hdmatx = NULL; + } + } + /* Abort the MMC DMA Rx Stream */ + if(hmmc->hdmarx != NULL) + { + hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort; + if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK) + { + hmmc->hdmarx = NULL; + } + } + } + + /* No transfer ongoing on both DMA channels*/ + if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL)) + { + CardState = HAL_MMC_GetCardState(hmmc); + hmmc->State = HAL_MMC_STATE_READY; + + if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) + { + hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance); + } + if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE) + { + return HAL_ERROR; + } + else + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->AbortCpltCallback(hmmc); +#else + HAL_MMC_AbortCallback(hmmc); +#endif + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private function ----------------------------------------------------------*/ +/** @addtogroup MMC_Private_Functions + * @{ + */ + +/** + * @brief DMA MMC transmit process complete callback + * @param hdma: DMA handle + * @retval None + */ +static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent); + + /* Enable DATAEND Interrupt */ + __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND)); +} + +/** + * @brief DMA MMC receive process complete callback + * @param hdma: DMA handle + * @retval None + */ +static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent); + uint32_t errorstate; + + /* Send stop command in multiblock write */ + if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA)) + { + errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } + } + + /* Disable the DMA transfer for transmit request by setting the DMAEN bit + in the MMC DCTRL register */ + hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + hmmc->State = HAL_MMC_STATE_READY; + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->RxCpltCallback(hmmc); +#else + HAL_MMC_RxCpltCallback(hmmc); +#endif +} + +/** + * @brief DMA MMC communication error callback + * @param hdma: DMA handle + * @retval None + */ +static void MMC_DMAError(DMA_HandleTypeDef *hdma) +{ + MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent); + HAL_MMC_CardStateTypeDef CardState; + uint32_t RxErrorCode, TxErrorCode; + + /* if DMA error is FIFO error ignore it */ + if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) + { + RxErrorCode = hmmc->hdmarx->ErrorCode; + TxErrorCode = hmmc->hdmatx->ErrorCode; + if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE)) + { + /* Clear All flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + + /* Disable All interrupts */ + __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + hmmc->ErrorCode |= HAL_MMC_ERROR_DMA; + CardState = HAL_MMC_GetCardState(hmmc); + if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) + { + hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance); + } + + hmmc->State= HAL_MMC_STATE_READY; + } + +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } +} + +/** + * @brief DMA MMC Tx Abort callback + * @param hdma: DMA handle + * @retval None + */ +static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma) +{ + MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent); + HAL_MMC_CardStateTypeDef CardState; + + if(hmmc->hdmatx != NULL) + { + hmmc->hdmatx = NULL; + } + + /* All DMA channels are aborted */ + if(hmmc->hdmarx == NULL) + { + CardState = HAL_MMC_GetCardState(hmmc); + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + hmmc->State = HAL_MMC_STATE_READY; + if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) + { + hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance); + + if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE) + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->AbortCpltCallback(hmmc); +#else + HAL_MMC_AbortCallback(hmmc); +#endif + } + else + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } + } + } +} + +/** + * @brief DMA MMC Rx Abort callback + * @param hdma: DMA handle + * @retval None + */ +static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma) +{ + MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent); + HAL_MMC_CardStateTypeDef CardState; + + if(hmmc->hdmarx != NULL) + { + hmmc->hdmarx = NULL; + } + + /* All DMA channels are aborted */ + if(hmmc->hdmatx == NULL) + { + CardState = HAL_MMC_GetCardState(hmmc); + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + hmmc->State = HAL_MMC_STATE_READY; + if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) + { + hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance); + + if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE) + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->AbortCpltCallback(hmmc); +#else + HAL_MMC_AbortCallback(hmmc); +#endif + } + else + { +#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) + hmmc->ErrorCallback(hmmc); +#else + HAL_MMC_ErrorCallback(hmmc); +#endif + } + } + } +} + +/** + * @brief Initializes the mmc card. + * @param hmmc: Pointer to MMC handle + * @retval MMC Card error state + */ +static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc) +{ + HAL_MMC_CardCSDTypeDef CSD; + uint32_t errorstate; + uint16_t mmc_rca = 2U; + MMC_InitTypeDef Init; + + /* Check the power State */ + if(SDIO_GetPowerState(hmmc->Instance) == 0U) + { + /* Power off */ + return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE; + } + + /* Send CMD2 ALL_SEND_CID */ + errorstate = SDMMC_CmdSendCID(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + else + { + /* Get Card identification number data */ + hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2); + hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3); + hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4); + } + + /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */ + /* MMC Card publishes its RCA. */ + errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + + /* Get the MMC card RCA */ + hmmc->MmcCard.RelCardAdd = mmc_rca; + + /* Send CMD9 SEND_CSD with argument as card's RCA */ + errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + else + { + /* Get Card Specific Data */ + hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2); + hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3); + hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4); + } + + /* Get the Card Class */ + hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U); + + /* Select the Card */ + errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + + /* Get CSD parameters */ + if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK) + { + return hmmc->ErrorCode; + } + + /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; + } + + /* Get Extended CSD parameters */ + if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK) + { + return hmmc->ErrorCode; + } + + /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; + } + + /* Configure the SDIO peripheral */ + Init = hmmc->Init; + Init.BusWide = SDIO_BUS_WIDE_1B; + (void)SDIO_Init(hmmc->Instance, Init); + + /* All cards are initialized */ + return HAL_MMC_ERROR_NONE; +} + +/** + * @brief Enquires cards about their operating voltage and configures clock + * controls and stores MMC information that will be needed in future + * in the MMC handle. + * @param hmmc: Pointer to MMC handle + * @retval error state + */ +static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc) +{ + __IO uint32_t count = 0U; + uint32_t response = 0U, validvoltage = 0U; + uint32_t errorstate; + + /* CMD0: GO_IDLE_STATE */ + errorstate = SDMMC_CmdGoIdleState(hmmc->Instance); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + + while(validvoltage == 0U) + { + if(count++ == SDMMC_MAX_VOLT_TRIAL) + { + return HAL_MMC_ERROR_INVALID_VOLTRANGE; + } + + /* SEND CMD1 APP_CMD with voltage range as argument */ + errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return HAL_MMC_ERROR_UNSUPPORTED_FEATURE; + } + + /* Get command response */ + response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + + /* Get operating voltage*/ + validvoltage = (((response >> 31U) == 1U) ? 1U : 0U); + } + + /* When power routine is finished and command returns valid voltage */ + if (((response & (0xFF000000U)) >> 24U) == 0xC0U) + { + hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD; + } + else + { + hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD; + } + + return HAL_MMC_ERROR_NONE; +} + +/** + * @brief Turns the SDIO output signals off. + * @param hmmc: Pointer to MMC handle + * @retval None + */ +static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc) +{ + /* Set Power State to OFF */ + (void)SDIO_PowerState_OFF(hmmc->Instance); +} + +/** + * @brief Returns the current card's status. + * @param hmmc: Pointer to MMC handle + * @param pCardStatus: pointer to the buffer that will contain the MMC card + * status (Card Status register) + * @retval error state + */ +static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus) +{ + uint32_t errorstate; + + if(pCardStatus == NULL) + { + return HAL_MMC_ERROR_PARAM; + } + + /* Send Status command */ + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + return errorstate; + } + + /* Get MMC card status */ + *pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + + return HAL_MMC_ERROR_NONE; +} + +/** + * @brief Reads extended CSD register to get the sectors number of the device + * @param hmmc: Pointer to MMC handle + * @param pFieldData: Pointer to the read buffer + * @param FieldIndex: Index of the field to be read + * @param Timeout: Specify timeout value + * @retval HAL status + */ +static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count; + uint32_t i = 0; + uint32_t tmp_data; + + hmmc->ErrorCode = HAL_MMC_ERROR_NONE; + + /* Initialize data control register */ + hmmc->Instance->DCTRL = 0; + + /* Configure the MMC DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = 512; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hmmc->Instance, &config); + + /* Set Block Size for Card */ + errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0); + if(errorstate != HAL_MMC_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= errorstate; + hmmc->State = HAL_MMC_STATE_READY; + return HAL_ERROR; + } + + /* Poll on SDMMC flags */ + while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) + { + if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF)) + { + /* Read data from SDMMC Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + tmp_data = SDIO_ReadFIFO(hmmc->Instance); + /* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */ + /* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */ + if ((i + count) == ((uint32_t)FieldIndex/4U)) + { + *pFieldData = tmp_data; + } + } + i += 8U; + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); + hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; + hmmc->State= HAL_MMC_STATE_READY; + return HAL_TIMEOUT; + } + } + + /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + hmmc->ErrorCode |= errorstate; + } + + /* Clear all the static flags */ + __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS); + + hmmc->State = HAL_MMC_STATE_READY; + + return HAL_OK; +} + + +/** + * @brief Wrap up reading in non-blocking mode. + * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains + * the configuration information. + * @retval None + */ +static void MMC_Read_IT(MMC_HandleTypeDef *hmmc) +{ + uint32_t count, data, dataremaining; + uint8_t* tmp; + + tmp = hmmc->pRxBuffPtr; + dataremaining = hmmc->RxXferSize; + + if (dataremaining > 0U) + { + /* Read data from SDIO Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = SDIO_ReadFIFO(hmmc->Instance); + *tmp = (uint8_t)(data & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 8U) & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 16U) & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 24U) & 0xFFU); + tmp++; + dataremaining--; + } + + hmmc->pRxBuffPtr = tmp; + hmmc->RxXferSize = dataremaining; + } +} + +/** + * @brief Wrap up writing in non-blocking mode. + * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains + * the configuration information. + * @retval None + */ +static void MMC_Write_IT(MMC_HandleTypeDef *hmmc) +{ + uint32_t count, data, dataremaining; + uint8_t* tmp; + + tmp = hmmc->pTxBuffPtr; + dataremaining = hmmc->TxXferSize; + + if (dataremaining > 0U) + { + /* Write data to SDIO Tx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = (uint32_t)(*tmp); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 8U); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 16U); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 24U); + tmp++; + dataremaining--; + (void)SDIO_WriteFIFO(hmmc->Instance, &data); + } + + hmmc->pTxBuffPtr = tmp; + hmmc->TxXferSize = dataremaining; + } +} + +/** + * @brief Update the power class of the device. + * @param hmmc MMC handle + * @param Wide Wide of MMC bus + * @param Speed Speed of the MMC bus + * @retval MMC Card error state + */ +static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide) +{ + uint32_t count; + uint32_t response = 0U; + uint32_t errorstate = HAL_MMC_ERROR_NONE; + uint32_t power_class, supported_pwr_class; + + if((Wide == SDIO_BUS_WIDE_8B) || (Wide == SDIO_BUS_WIDE_4B)) + { + power_class = 0U; /* Default value after power-on or software reset */ + + /* Read the PowerClass field of the Extended CSD register */ + if(MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */ + { + errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; + } + else + { + power_class = ((power_class >> 24U) & 0x000000FFU); + } + + /* Get the supported PowerClass field of the Extended CSD register */ + /* Field PWR_CL_26_xxx [201 or 203] */ + supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX/4)] >> MMC_EXT_CSD_PWR_CL_26_POS) & 0x000000FFU); + + if(errorstate == HAL_MMC_ERROR_NONE) + { + if(Wide == SDIO_BUS_WIDE_8B) + { + /* Bit [7:4] : power class for 8-bits bus configuration - Bit [3:0] : power class for 4-bits bus configuration */ + supported_pwr_class = (supported_pwr_class >> 4U); + } + + if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU)) + { + /* Need to change current power class */ + errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U))); + + if(errorstate == HAL_MMC_ERROR_NONE) + { + /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ + count = SDMMC_MAX_TRIAL; + do + { + errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); + if(errorstate != HAL_MMC_ERROR_NONE) + { + break; + } + + /* Get command response */ + response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1); + count--; + }while(((response & 0x100U) == 0U) && (count != 0U)); + + /* Check the status after the switch command execution */ + if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) + { + /* Check the bit SWITCH_ERROR of the device status */ + if ((response & 0x80U) != 0U) + { + errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; + } + } + else if (count == 0U) + { + errorstate = SDMMC_ERROR_TIMEOUT; + } + else + { + /* Nothing to do */ + } + } + } + } + } + + return errorstate; +} + +/** + * @} + */ + +#endif /* SDIO */ + +#endif /* HAL_MMC_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c new file mode 100644 index 0000000..82de111 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_msp_template.c @@ -0,0 +1,100 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_msp_template.c + * @author MCD Application Team + * @brief This file contains the HAL System and Peripheral (PPP) MSP initialization + * and de-initialization functions. + * It should be copied to the application folder and renamed into 'stm32f4xx_hal_msp.c'. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup HAL_MSP HAL MSP + * @brief HAL MSP module. + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup HAL_MSP_Private_Functions HAL MSP Private Functions + * @{ + */ + +/** + * @brief Initializes the Global MSP. + * @note This function is called from HAL_Init() function to perform system + * level initialization (GPIOs, clock, DMA, interrupt). + * @retval None + */ +void HAL_MspInit(void) +{ + +} + +/** + * @brief DeInitializes the Global MSP. + * @note This functiona is called from HAL_DeInit() function to perform system + * level de-initialization (GPIOs, clock, DMA, interrupt). + * @retval None + */ +void HAL_MspDeInit(void) +{ + +} + +/** + * @brief Initializes the PPP MSP. + * @note This functiona is called from HAL_PPP_Init() function to perform + * peripheral(PPP) system level initialization (GPIOs, clock, DMA, interrupt) + * @retval None + */ +void HAL_PPP_MspInit(void) +{ + +} + +/** + * @brief DeInitializes the PPP MSP. + * @note This functiona is called from HAL_PPP_DeInit() function to perform + * peripheral(PPP) system level de-initialization (GPIOs, clock, DMA, interrupt) + * @retval None + */ +void HAL_PPP_MspDeInit(void) +{ + +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c new file mode 100644 index 0000000..a0b89e6 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nand.c @@ -0,0 +1,2405 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_nand.c + * @author MCD Application Team + * @brief NAND HAL module driver. + * This file provides a generic firmware to drive NAND memories mounted + * as external device. + * + ****************************************************************************** + * @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 ##### + ============================================================================== + [..] + This driver is a generic layered driver which contains a set of APIs used to + control NAND flash memories. It uses the FMC/FSMC layer functions to interface + with NAND devices. This driver is used as follows: + + (+) NAND flash memory configuration sequence using the function HAL_NAND_Init() + with control and timing parameters for both common and attribute spaces. + + (+) Read NAND flash memory maker and device IDs using the function + HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef + structure declared by the function caller. + + (+) Access NAND flash memory by read/write operations using the functions + HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(), + HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(), + HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(), + HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b() + to read/write page(s)/spare area(s). These functions use specific device + information (Block, page size..) predefined by the user in the NAND_DeviceConfigTypeDef + structure. The read/write address information is contained by the Nand_Address_Typedef + structure passed as parameter. + + (+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset(). + + (+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block(). + The erase block address information is contained in the Nand_Address_Typedef + structure passed as parameter. + + (+) Read the NAND flash status operation using the function HAL_NAND_Read_Status(). + + (+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/ + HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction + feature or the function HAL_NAND_GetECC() to get the ECC correction code. + + (+) You can monitor the NAND device HAL state by calling the function + HAL_NAND_GetState() + + [..] + (@) This driver is a set of generic APIs which handle standard NAND flash operations. + If a NAND flash device contains different operations and/or implementations, + it should be implemented separately. + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_NAND_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_NAND_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) MspInitCallback : NAND MspInit. + (+) MspDeInitCallback : NAND MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_NAND_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) MspInitCallback : NAND MspInit. + (+) MspDeInitCallback : NAND MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_NAND_Init + and HAL_NAND_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_NAND_Init and HAL_NAND_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_NAND_RegisterCallback before calling HAL_NAND_DeInit + or HAL_NAND_Init function. + + When The compilation define USE_HAL_NAND_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_NAND_MODULE_ENABLED + +/** @defgroup NAND NAND + * @brief NAND HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private Constants ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup NAND_Exported_Functions NAND Exported Functions + * @{ + */ + +/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### NAND Initialization and de-initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize + the NAND memory + +@endverbatim + * @{ + */ + +/** + * @brief Perform NAND memory Initialization sequence + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param ComSpace_Timing pointer to Common space timing structure + * @param AttSpace_Timing pointer to Attribute space timing structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FMC_NAND_PCC_TimingTypeDef *ComSpace_Timing, + FMC_NAND_PCC_TimingTypeDef *AttSpace_Timing) +{ + /* Check the NAND handle state */ + if (hnand == NULL) + { + return HAL_ERROR; + } + + if (hnand->State == HAL_NAND_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hnand->Lock = HAL_UNLOCKED; + +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + if (hnand->MspInitCallback == NULL) + { + hnand->MspInitCallback = HAL_NAND_MspInit; + } + hnand->ItCallback = HAL_NAND_ITCallback; + + /* Init the low level hardware */ + hnand->MspInitCallback(hnand); +#else + /* Initialize the low level hardware (MSP) */ + HAL_NAND_MspInit(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + } + + /* Initialize NAND control Interface */ + (void)FMC_NAND_Init(hnand->Instance, &(hnand->Init)); + + /* Initialize NAND common space timing Interface */ + (void)FMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank); + + /* Initialize NAND attribute space timing Interface */ + (void)FMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank); + + /* Enable the NAND device */ +#if defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + __FMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank); +#else + __FMC_NAND_ENABLE(hnand->Instance); +#endif + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Perform NAND memory De-Initialization sequence + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand) +{ +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + if (hnand->MspDeInitCallback == NULL) + { + hnand->MspDeInitCallback = HAL_NAND_MspDeInit; + } + + /* DeInit the low level hardware */ + hnand->MspDeInitCallback(hnand); +#else + /* Initialize the low level hardware (MSP) */ + HAL_NAND_MspDeInit(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + + /* Configure the NAND registers with their reset values */ + (void)FMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank); + + /* Reset the NAND controller state */ + hnand->State = HAL_NAND_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hnand); + + return HAL_OK; +} + +/** + * @brief NAND MSP Init + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval None + */ +__weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnand); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NAND_MspInit could be implemented in the user file + */ +} + +/** + * @brief NAND MSP DeInit + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval None + */ +__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnand); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NAND_MspDeInit could be implemented in the user file + */ +} + + +/** + * @brief This function handles NAND device interrupt request. + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL status + */ +void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand) +{ + /* Check NAND interrupt Rising edge flag */ + if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE)) + { + /* NAND interrupt callback*/ +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + hnand->ItCallback(hnand); +#else + HAL_NAND_ITCallback(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + + /* Clear NAND interrupt Rising edge pending bit */ +#if defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_RISING_EDGE); +#else + __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_RISING_EDGE); +#endif /* FMC_Bank2_3 || FSMC_Bank2_3 */ + } + + /* Check NAND interrupt Level flag */ + if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL)) + { + /* NAND interrupt callback*/ +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + hnand->ItCallback(hnand); +#else + HAL_NAND_ITCallback(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + + /* Clear NAND interrupt Level pending bit */ +#if defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_LEVEL); +#else + __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_LEVEL); +#endif /* FMC_Bank2_3 || FSMC_Bank2_3 */ + } + + /* Check NAND interrupt Falling edge flag */ + if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE)) + { + /* NAND interrupt callback*/ +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + hnand->ItCallback(hnand); +#else + HAL_NAND_ITCallback(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + + /* Clear NAND interrupt Falling edge pending bit */ +#if defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FALLING_EDGE); +#else + __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FALLING_EDGE); +#endif /* FMC_Bank2_3 || FSMC_Bank2_3 */ + } + + /* Check NAND interrupt FIFO empty flag */ + if (__FMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT)) + { + /* NAND interrupt callback*/ +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) + hnand->ItCallback(hnand); +#else + HAL_NAND_ITCallback(hnand); +#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */ + + /* Clear NAND interrupt FIFO empty pending bit */ +#if defined(FMC_Bank2_3) || defined(FSMC_Bank2_3) + __FMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FMC_FLAG_FEMPT); +#else + __FMC_NAND_CLEAR_FLAG(hnand->Instance, FMC_FLAG_FEMPT); +#endif /* FMC_Bank2_3 || FSMC_Bank2_3 */ + } + +} + +/** + * @brief NAND interrupt feature callback + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval None + */ +__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnand); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NAND_ITCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions + * @brief Input Output and memory control functions + * + @verbatim + ============================================================================== + ##### NAND Input and Output functions ##### + ============================================================================== + [..] + This section provides functions allowing to use and control the NAND + memory + +@endverbatim + * @{ + */ + +/** + * @brief Read the NAND memory electronic signature + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pNAND_ID NAND ID structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID) +{ + __IO uint32_t data = 0; + __IO uint32_t data1 = 0; + uint32_t deviceaddress; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* Send Read ID command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00; + __DSB(); + + /* Read the electronic signature from NAND flash */ +#ifdef FSMC_PCR2_PWID + if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) +#else /* FMC_PCR2_PWID is defined */ + if (hnand->Init.MemoryDataWidth == FMC_NAND_PCC_MEM_BUS_WIDTH_8) +#endif + { + data = *(__IO uint32_t *)deviceaddress; + + /* Return the data read */ + pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); + pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data); + pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data); + pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data); + } + else + { + data = *(__IO uint32_t *)deviceaddress; + data1 = *((__IO uint32_t *)deviceaddress + 4); + + /* Return the data read */ + pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data); + pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data); + pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1); + pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief NAND memory reset + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand) +{ + uint32_t deviceaddress; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* Send NAND reset command */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF; + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; + +} + +/** + * @brief Configure the device: Enter the physical parameters of the device + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, NAND_DeviceConfigTypeDef *pDeviceConfig) +{ + hnand->Config.PageSize = pDeviceConfig->PageSize; + hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize; + hnand->Config.BlockSize = pDeviceConfig->BlockSize; + hnand->Config.BlockNbr = pDeviceConfig->BlockNbr; + hnand->Config.PlaneSize = pDeviceConfig->PlaneSize; + hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr; + hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable; + + return HAL_OK; +} + +/** + * @brief Read Page(s) from NAND memory block (8-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to destination read buffer + * @param NumPageToRead number of pages to read from block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, + uint32_t NumPageToRead) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numpagesread = 0U; + uint32_t nandaddress; + uint32_t nbpages = NumPageToRead; + uint8_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Page(s) read loop */ + while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Send read page command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + __DSB(); + + + if (hnand->Config.ExtraCommandEnable == ENABLE) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Go back to read mode */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); + __DSB(); + } + + /* Get Data into Buffer */ + for (index = 0U; index < hnand->Config.PageSize; index++) + { + *buff = *(uint8_t *)deviceaddress; + buff++; + } + + /* Increment read pages number */ + numpagesread++; + + /* Decrement pages to read */ + nbpages--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Read Page(s) from NAND memory block (16-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned + * @param NumPageToRead number of pages to read from block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, + uint32_t NumPageToRead) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numpagesread = 0U; + uint32_t nandaddress; + uint32_t nbpages = NumPageToRead; + uint16_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Page(s) read loop */ + while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Send read page command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + __DSB(); + + if (hnand->Config.ExtraCommandEnable == ENABLE) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Go back to read mode */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); + __DSB(); + } + + /* Calculate PageSize */ +#if defined(FSMC_PCR2_PWID) + if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) +#else + if (hnand->Init.MemoryDataWidth == FMC_NAND_PCC_MEM_BUS_WIDTH_8) +#endif /* FSMC_PCR2_PWID */ + { + hnand->Config.PageSize = hnand->Config.PageSize / 2U; + } + else + { + /* Do nothing */ + /* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/ + } + + /* Get Data into Buffer */ + for (index = 0U; index < hnand->Config.PageSize; index++) + { + *buff = *(uint16_t *)deviceaddress; + buff++; + } + + /* Increment read pages number */ + numpagesread++; + + /* Decrement pages to read */ + nbpages--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Write Page(s) to NAND memory block (8-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write + * @param NumPageToWrite number of pages to write to block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, + uint32_t NumPageToWrite) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numpageswritten = 0U; + uint32_t nandaddress; + uint32_t nbpages = NumPageToWrite; + uint8_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Page(s) write loop */ + while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Send write page command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + /* Write data to memory */ + for (index = 0U; index < hnand->Config.PageSize; index++) + { + *(__IO uint8_t *)deviceaddress = *buff; + buff++; + __DSB(); + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + __DSB(); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Increment written pages number */ + numpageswritten++; + + /* Decrement pages to write */ + nbpages--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Write Page(s) to NAND memory block (16-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned + * @param NumPageToWrite number of pages to write to block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint16_t *pBuffer, + uint32_t NumPageToWrite) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numpageswritten = 0U; + uint32_t nandaddress; + uint32_t nbpages = NumPageToWrite; + uint16_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Page(s) write loop */ + while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Send write page command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + /* Calculate PageSize */ +#if defined(FSMC_PCR2_PWID) + if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8) +#else + if (hnand->Init.MemoryDataWidth == FMC_NAND_PCC_MEM_BUS_WIDTH_8) +#endif /* FSMC_PCR2_PWID */ + { + hnand->Config.PageSize = hnand->Config.PageSize / 2U; + } + else + { + /* Do nothing */ + /* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/ + } + + /* Write data to memory */ + for (index = 0U; index < hnand->Config.PageSize; index++) + { + *(__IO uint16_t *)deviceaddress = *buff; + buff++; + __DSB(); + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + __DSB(); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Increment written pages number */ + numpageswritten++; + + /* Decrement pages to write */ + nbpages--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Read Spare area(s) from NAND memory (8-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write + * @param NumSpareAreaToRead Number of spare area to read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, uint8_t *pBuffer, + uint32_t NumSpareAreaToRead) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numsparearearead = 0U; + uint32_t nandaddress; + uint32_t columnaddress; + uint32_t nbspare = NumSpareAreaToRead; + uint8_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Column in page address */ + columnaddress = COLUMN_ADDRESS(hnand); + + /* Spare area(s) read loop */ + while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + /* Send read spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + /* Send read spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + __DSB(); + + if (hnand->Config.ExtraCommandEnable == ENABLE) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Go back to read mode */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); + __DSB(); + } + + /* Get Data into Buffer */ + for (index = 0U; index < hnand->Config.SpareAreaSize; index++) + { + *buff = *(uint8_t *)deviceaddress; + buff++; + } + + /* Increment read spare areas number */ + numsparearearead++; + + /* Decrement spare areas to read */ + nbspare--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Read Spare area(s) from NAND memory (16-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. + * @param NumSpareAreaToRead Number of spare area to read + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint16_t *pBuffer, uint32_t NumSpareAreaToRead) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numsparearearead = 0U; + uint32_t nandaddress; + uint32_t columnaddress; + uint32_t nbspare = NumSpareAreaToRead; + uint16_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Column in page address */ + columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand)); + + /* Spare area(s) read loop */ + while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + /* Send read spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + /* Send read spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1; + __DSB(); + + if (hnand->Config.ExtraCommandEnable == ENABLE) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Go back to read mode */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00); + __DSB(); + } + + /* Get Data into Buffer */ + for (index = 0U; index < hnand->Config.SpareAreaSize; index++) + { + *buff = *(uint16_t *)deviceaddress; + buff++; + } + + /* Increment read spare areas number */ + numsparearearead++; + + /* Decrement spare areas to read */ + nbspare--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Write Spare area(s) to NAND memory (8-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write + * @param NumSpareAreaTowrite number of spare areas to write to block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint8_t *pBuffer, uint32_t NumSpareAreaTowrite) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numspareareawritten = 0U; + uint32_t nandaddress; + uint32_t columnaddress; + uint32_t nbspare = NumSpareAreaTowrite; + uint8_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* Page address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Column in page address */ + columnaddress = COLUMN_ADDRESS(hnand); + + /* Spare area(s) write loop */ + while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + /* Send write Spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + /* Send write Spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + /* Write data to memory */ + for (index = 0U; index < hnand->Config.SpareAreaSize; index++) + { + *(__IO uint8_t *)deviceaddress = *buff; + buff++; + __DSB(); + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + __DSB(); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Increment written spare areas number */ + numspareareawritten++; + + /* Decrement spare areas to write */ + nbspare--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Write Spare area(s) to NAND memory (16-bits addressing) + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned. + * @param NumSpareAreaTowrite number of spare areas to write to block + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress, + uint16_t *pBuffer, uint32_t NumSpareAreaTowrite) +{ + uint32_t index; + uint32_t tickstart; + uint32_t deviceaddress; + uint32_t numspareareawritten = 0U; + uint32_t nandaddress; + uint32_t columnaddress; + uint32_t nbspare = NumSpareAreaTowrite; + uint16_t *buff = pBuffer; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* NAND raw address calculation */ + nandaddress = ARRAY_ADDRESS(pAddress, hnand); + + /* Column in page address */ + columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand)); + + /* Spare area(s) write loop */ + while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)))) + { + /* Cards with page size <= 512 bytes */ + if ((hnand->Config.PageSize) <= 512U) + { + /* Send write Spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + else /* (hnand->Config.PageSize) > 512 */ + { + /* Send write Spare area command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0; + __DSB(); + + if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U) + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + } + else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */ + { + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress); + __DSB(); + } + } + + /* Write data to memory */ + for (index = 0U; index < hnand->Config.SpareAreaSize; index++) + { + *(__IO uint16_t *)deviceaddress = *buff; + buff++; + __DSB(); + } + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1; + __DSB(); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Read status until NAND is ready */ + while (HAL_NAND_Read_Status(hnand) != NAND_READY) + { + if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT) + { + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + + return HAL_TIMEOUT; + } + } + + /* Increment written spare areas number */ + numspareareawritten++; + + /* Decrement spare areas to write */ + nbspare--; + + /* Increment the NAND address */ + nandaddress = (uint32_t)(nandaddress + 1U); + } + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief NAND memory Block erase + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) +{ + uint32_t deviceaddress; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnand); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* Send Erase block command sequence */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0; + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); + __DSB(); + *(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand)); + __DSB(); + + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1; + __DSB(); + + /* Update the NAND controller state */ + hnand->State = HAL_NAND_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnand); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Increment the NAND memory address + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param pAddress pointer to NAND address structure + * @retval The new status of the increment address operation. It can be: + * - NAND_VALID_ADDRESS: When the new address is valid address + * - NAND_INVALID_ADDRESS: When the new address is invalid address + */ +uint32_t HAL_NAND_Address_Inc(NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress) +{ + uint32_t status = NAND_VALID_ADDRESS; + + /* Increment page address */ + pAddress->Page++; + + /* Check NAND address is valid */ + if (pAddress->Page == hnand->Config.BlockSize) + { + pAddress->Page = 0; + pAddress->Block++; + + if (pAddress->Block == hnand->Config.PlaneSize) + { + pAddress->Block = 0; + pAddress->Plane++; + + if (pAddress->Plane == (hnand->Config.PlaneNbr)) + { + status = NAND_INVALID_ADDRESS; + } + } + } + + return (status); +} + +#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User NAND Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hnand : NAND handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID + * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID + * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId, + pNAND_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hnand); + + if (hnand->State == HAL_NAND_STATE_READY) + { + switch (CallbackId) + { + case HAL_NAND_MSP_INIT_CB_ID : + hnand->MspInitCallback = pCallback; + break; + case HAL_NAND_MSP_DEINIT_CB_ID : + hnand->MspDeInitCallback = pCallback; + break; + case HAL_NAND_IT_CB_ID : + hnand->ItCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hnand->State == HAL_NAND_STATE_RESET) + { + switch (CallbackId) + { + case HAL_NAND_MSP_INIT_CB_ID : + hnand->MspInitCallback = pCallback; + break; + case HAL_NAND_MSP_DEINIT_CB_ID : + hnand->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hnand); + return status; +} + +/** + * @brief Unregister a User NAND Callback + * NAND Callback is redirected to the weak (surcharged) predefined callback + * @param hnand : NAND handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID + * @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID + * @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hnand); + + if (hnand->State == HAL_NAND_STATE_READY) + { + switch (CallbackId) + { + case HAL_NAND_MSP_INIT_CB_ID : + hnand->MspInitCallback = HAL_NAND_MspInit; + break; + case HAL_NAND_MSP_DEINIT_CB_ID : + hnand->MspDeInitCallback = HAL_NAND_MspDeInit; + break; + case HAL_NAND_IT_CB_ID : + hnand->ItCallback = HAL_NAND_ITCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hnand->State == HAL_NAND_STATE_RESET) + { + switch (CallbackId) + { + case HAL_NAND_MSP_INIT_CB_ID : + hnand->MspInitCallback = HAL_NAND_MspInit; + break; + case HAL_NAND_MSP_DEINIT_CB_ID : + hnand->MspDeInitCallback = HAL_NAND_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hnand); + return status; +} +#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions + * @brief management functions + * +@verbatim + ============================================================================== + ##### NAND Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the NAND interface. + +@endverbatim + * @{ + */ + + +/** + * @brief Enables dynamically NAND ECC feature. + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand) +{ + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Enable ECC feature */ + (void)FMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank); + + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically FMC_NAND ECC feature. + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand) +{ + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Disable ECC feature */ + (void)FMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank); + + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically NAND ECC feature. + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @param ECCval pointer to ECC value + * @param Timeout maximum timeout to wait + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + + /* Check the NAND controller state */ + if (hnand->State == HAL_NAND_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnand->State == HAL_NAND_STATE_READY) + { + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_BUSY; + + /* Get NAND ECC value */ + status = FMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout); + + /* Update the NAND state */ + hnand->State = HAL_NAND_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @} + */ + + +/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### NAND State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the NAND controller + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief return the NAND state + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval HAL state + */ +HAL_NAND_StateTypeDef HAL_NAND_GetState(NAND_HandleTypeDef *hnand) +{ + return hnand->State; +} + +/** + * @brief NAND memory read status + * @param hnand pointer to a NAND_HandleTypeDef structure that contains + * the configuration information for NAND module. + * @retval NAND status + */ +uint32_t HAL_NAND_Read_Status(NAND_HandleTypeDef *hnand) +{ + uint32_t data; + uint32_t deviceaddress; + UNUSED(hnand); + + /* Identify the device address */ +#if defined(FMC_Bank2_3) + if (hnand->Init.NandBank == FMC_NAND_BANK2) + { + deviceaddress = NAND_DEVICE1; + } + else + { + deviceaddress = NAND_DEVICE2; + } +#else + deviceaddress = NAND_DEVICE; +#endif + + /* Send Read status operation command */ + *(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS; + + /* Read status register data */ + data = *(__IO uint8_t *)deviceaddress; + + /* Return the status */ + if ((data & NAND_ERROR) == NAND_ERROR) + { + return NAND_ERROR; + } + else if ((data & NAND_READY) == NAND_READY) + { + return NAND_READY; + } + else + { + return NAND_BUSY; + } +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_NAND_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* FMC_Bank3) || defined(FMC_Bank2_3) || defined(FSMC_Bank2_3 */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c new file mode 100644 index 0000000..0a82044 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_nor.c @@ -0,0 +1,1543 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_nor.c + * @author MCD Application Team + * @brief NOR HAL module driver. + * This file provides a generic firmware to drive NOR memories mounted + * as external device. + * + ****************************************************************************** + * @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 ##### + ============================================================================== + [..] + This driver is a generic layered driver which contains a set of APIs used to + control NOR flash memories. It uses the FMC/FSMC layer functions to interface + with NOR devices. This driver is used as follows: + + (+) NOR flash memory configuration sequence using the function HAL_NOR_Init() + with control and timing parameters for both normal and extended mode. + + (+) Read NOR flash memory manufacturer code and device IDs using the function + HAL_NOR_Read_ID(). The read information is stored in the NOR_ID_TypeDef + structure declared by the function caller. + + (+) Access NOR flash memory by read/write data unit operations using the functions + HAL_NOR_Read(), HAL_NOR_Program(). + + (+) Perform NOR flash erase block/chip operations using the functions + HAL_NOR_Erase_Block() and HAL_NOR_Erase_Chip(). + + (+) Read the NOR flash CFI (common flash interface) IDs using the function + HAL_NOR_Read_CFI(). The read information is stored in the NOR_CFI_TypeDef + structure declared by the function caller. + + (+) You can also control the NOR device by calling the control APIs HAL_NOR_WriteOperation_Enable()/ + HAL_NOR_WriteOperation_Disable() to respectively enable/disable the NOR write operation + + (+) You can monitor the NOR device HAL state by calling the function + HAL_NOR_GetState() + [..] + (@) This driver is a set of generic APIs which handle standard NOR flash operations. + If a NOR flash device contains different operations and/or implementations, + it should be implemented separately. + + *** NOR HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in NOR HAL driver. + + (+) NOR_WRITE : NOR memory write data to specified address + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_NOR_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_NOR_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) MspInitCallback : NOR MspInit. + (+) MspDeInitCallback : NOR MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_NOR_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) MspInitCallback : NOR MspInit. + (+) MspDeInitCallback : NOR MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_NOR_Init and if the state is HAL_NOR_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_NOR_Init + and HAL_NOR_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_NOR_Init and HAL_NOR_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_NOR_RegisterCallback before calling HAL_NOR_DeInit + or HAL_NOR_Init function. + + When The compilation define USE_HAL_NOR_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(FMC_Bank1) || defined(FSMC_Bank1) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_NOR_MODULE_ENABLED + +/** @defgroup NOR NOR + * @brief NOR driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup NOR_Private_Defines NOR Private Defines + * @{ + */ + +/* Constants to define address to set to write a command */ +#define NOR_CMD_ADDRESS_FIRST (uint16_t)0x0555 +#define NOR_CMD_ADDRESS_FIRST_CFI (uint16_t)0x0055 +#define NOR_CMD_ADDRESS_SECOND (uint16_t)0x02AA +#define NOR_CMD_ADDRESS_THIRD (uint16_t)0x0555 +#define NOR_CMD_ADDRESS_FOURTH (uint16_t)0x0555 +#define NOR_CMD_ADDRESS_FIFTH (uint16_t)0x02AA +#define NOR_CMD_ADDRESS_SIXTH (uint16_t)0x0555 + +/* Constants to define data to program a command */ +#define NOR_CMD_DATA_READ_RESET (uint16_t)0x00F0 +#define NOR_CMD_DATA_FIRST (uint16_t)0x00AA +#define NOR_CMD_DATA_SECOND (uint16_t)0x0055 +#define NOR_CMD_DATA_AUTO_SELECT (uint16_t)0x0090 +#define NOR_CMD_DATA_PROGRAM (uint16_t)0x00A0 +#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD (uint16_t)0x0080 +#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH (uint16_t)0x00AA +#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH (uint16_t)0x0055 +#define NOR_CMD_DATA_CHIP_ERASE (uint16_t)0x0010 +#define NOR_CMD_DATA_CFI (uint16_t)0x0098 + +#define NOR_CMD_DATA_BUFFER_AND_PROG (uint8_t)0x25 +#define NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM (uint8_t)0x29 +#define NOR_CMD_DATA_BLOCK_ERASE (uint8_t)0x30 + +#define NOR_CMD_READ_ARRAY (uint16_t)0x00FF +#define NOR_CMD_WORD_PROGRAM (uint16_t)0x0040 +#define NOR_CMD_BUFFERED_PROGRAM (uint16_t)0x00E8 +#define NOR_CMD_CONFIRM (uint16_t)0x00D0 +#define NOR_CMD_BLOCK_ERASE (uint16_t)0x0020 +#define NOR_CMD_BLOCK_UNLOCK (uint16_t)0x0060 +#define NOR_CMD_READ_STATUS_REG (uint16_t)0x0070 +#define NOR_CMD_CLEAR_STATUS_REG (uint16_t)0x0050 + +/* Mask on NOR STATUS REGISTER */ +#define NOR_MASK_STATUS_DQ4 (uint16_t)0x0010 +#define NOR_MASK_STATUS_DQ5 (uint16_t)0x0020 +#define NOR_MASK_STATUS_DQ6 (uint16_t)0x0040 +#define NOR_MASK_STATUS_DQ7 (uint16_t)0x0080 + +/* Address of the primary command set */ +#define NOR_ADDRESS_COMMAND_SET (uint16_t)0x0013 + +/* Command set code assignment (defined in JEDEC JEP137B version may 2004) */ +#define NOR_INTEL_SHARP_EXT_COMMAND_SET (uint16_t)0x0001 /* Supported in this driver */ +#define NOR_AMD_FUJITSU_COMMAND_SET (uint16_t)0x0002 /* Supported in this driver */ +#define NOR_INTEL_STANDARD_COMMAND_SET (uint16_t)0x0003 /* Not Supported in this driver */ +#define NOR_AMD_FUJITSU_EXT_COMMAND_SET (uint16_t)0x0004 /* Not Supported in this driver */ +#define NOR_WINDBOND_STANDARD_COMMAND_SET (uint16_t)0x0006 /* Not Supported in this driver */ +#define NOR_MITSUBISHI_STANDARD_COMMAND_SET (uint16_t)0x0100 /* Not Supported in this driver */ +#define NOR_MITSUBISHI_EXT_COMMAND_SET (uint16_t)0x0101 /* Not Supported in this driver */ +#define NOR_PAGE_WRITE_COMMAND_SET (uint16_t)0x0102 /* Not Supported in this driver */ +#define NOR_INTEL_PERFORMANCE_COMMAND_SET (uint16_t)0x0200 /* Not Supported in this driver */ +#define NOR_INTEL_DATA_COMMAND_SET (uint16_t)0x0210 /* Not Supported in this driver */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/** @defgroup NOR_Private_Variables NOR Private Variables + * @{ + */ + +static uint32_t uwNORMemoryDataWidth = NOR_MEMORY_8B; + +/** + * @} + */ + +/* Private functions ---------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup NOR_Exported_Functions NOR Exported Functions + * @{ + */ + +/** @defgroup NOR_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### NOR Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize + the NOR memory + +@endverbatim + * @{ + */ + +/** + * @brief Perform the NOR memory Initialization sequence + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param Timing pointer to NOR control timing structure + * @param ExtTiming pointer to NOR extended mode timing structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Init(NOR_HandleTypeDef *hnor, FMC_NORSRAM_TimingTypeDef *Timing, + FMC_NORSRAM_TimingTypeDef *ExtTiming) +{ + uint32_t deviceaddress; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR handle parameter */ + if (hnor == NULL) + { + return HAL_ERROR; + } + + if (hnor->State == HAL_NOR_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hnor->Lock = HAL_UNLOCKED; + +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) + if (hnor->MspInitCallback == NULL) + { + hnor->MspInitCallback = HAL_NOR_MspInit; + } + + /* Init the low level hardware */ + hnor->MspInitCallback(hnor); +#else + /* Initialize the low level hardware (MSP) */ + HAL_NOR_MspInit(hnor); +#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */ + } + + /* Initialize NOR control Interface */ + (void)FMC_NORSRAM_Init(hnor->Instance, &(hnor->Init)); + + /* Initialize NOR timing Interface */ + (void)FMC_NORSRAM_Timing_Init(hnor->Instance, Timing, hnor->Init.NSBank); + + /* Initialize NOR extended mode timing Interface */ + (void)FMC_NORSRAM_Extended_Timing_Init(hnor->Extended, ExtTiming, hnor->Init.NSBank, hnor->Init.ExtendedMode); + + /* Enable the NORSRAM device */ + __FMC_NORSRAM_ENABLE(hnor->Instance, hnor->Init.NSBank); + + /* Initialize NOR Memory Data Width*/ + if (hnor->Init.MemoryDataWidth == FMC_NORSRAM_MEM_BUS_WIDTH_8) + { + uwNORMemoryDataWidth = NOR_MEMORY_8B; + } + else + { + uwNORMemoryDataWidth = NOR_MEMORY_16B; + } + + /* Initialize the NOR controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + if (hnor->Init.WriteOperation == FMC_WRITE_OPERATION_DISABLE) + { + (void)FMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_PROTECTED; + } + else + { + /* Get the value of the command set */ + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI); + hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET); + + status = HAL_NOR_ReturnToReadMode(hnor); + } + + return status; +} + +/** + * @brief Perform NOR memory De-Initialization sequence + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_DeInit(NOR_HandleTypeDef *hnor) +{ +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) + if (hnor->MspDeInitCallback == NULL) + { + hnor->MspDeInitCallback = HAL_NOR_MspDeInit; + } + + /* DeInit the low level hardware */ + hnor->MspDeInitCallback(hnor); +#else + /* De-Initialize the low level hardware (MSP) */ + HAL_NOR_MspDeInit(hnor); +#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */ + + /* Configure the NOR registers with their reset values */ + (void)FMC_NORSRAM_DeInit(hnor->Instance, hnor->Extended, hnor->Init.NSBank); + + /* Reset the NOR controller state */ + hnor->State = HAL_NOR_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hnor); + + return HAL_OK; +} + +/** + * @brief NOR MSP Init + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_NOR_MspInit(NOR_HandleTypeDef *hnor) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NOR_MspInit could be implemented in the user file + */ +} + +/** + * @brief NOR MSP DeInit + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval None + */ +__weak void HAL_NOR_MspDeInit(NOR_HandleTypeDef *hnor) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NOR_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief NOR MSP Wait for Ready/Busy signal + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param Timeout Maximum timeout value + * @retval None + */ +__weak void HAL_NOR_MspWait(NOR_HandleTypeDef *hnor, uint32_t Timeout) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hnor); + UNUSED(Timeout); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_NOR_MspWait could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup NOR_Exported_Functions_Group2 Input and Output functions + * @brief Input Output and memory control functions + * + @verbatim + ============================================================================== + ##### NOR Input and Output functions ##### + ============================================================================== + [..] + This section provides functions allowing to use and control the NOR memory + +@endverbatim + * @{ + */ + +/** + * @brief Read NOR flash IDs + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pNOR_ID pointer to NOR ID structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Read_ID(NOR_HandleTypeDef *hnor, NOR_IDTypeDef *pNOR_ID) +{ + uint32_t deviceaddress; + HAL_NOR_StateTypeDef state; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + state = hnor->State; + if (state == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_NOR_STATE_PROTECTED) + { + return HAL_ERROR; + } + else if (state == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send read ID command */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_AUTO_SELECT); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE(deviceaddress, NOR_CMD_DATA_AUTO_SELECT); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + if (status != HAL_ERROR) + { + /* Read the NOR IDs */ + pNOR_ID->Manufacturer_Code = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, MC_ADDRESS); + pNOR_ID->Device_Code1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, + DEVICE_CODE1_ADDR); + pNOR_ID->Device_Code2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, + DEVICE_CODE2_ADDR); + pNOR_ID->Device_Code3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, + DEVICE_CODE3_ADDR); + } + + /* Check the NOR controller state */ + hnor->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Returns the NOR memory to Read mode. + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_ReturnToReadMode(NOR_HandleTypeDef *hnor) +{ + uint32_t deviceaddress; + HAL_NOR_StateTypeDef state; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + state = hnor->State; + if (state == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_NOR_STATE_PROTECTED) + { + return HAL_ERROR; + } + else if (state == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(deviceaddress, NOR_CMD_DATA_READ_RESET); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + /* Check the NOR controller state */ + hnor->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Read data from NOR memory + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress pointer to Device address + * @param pData pointer to read data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData) +{ + uint32_t deviceaddress; + HAL_NOR_StateTypeDef state; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + state = hnor->State; + if (state == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_NOR_STATE_PROTECTED) + { + return HAL_ERROR; + } + else if (state == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send read data command */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_READ_RESET); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE(pAddress, NOR_CMD_READ_ARRAY); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + if (status != HAL_ERROR) + { + /* Read the data */ + *pData = (uint16_t)(*(__IO uint32_t *)pAddress); + } + + /* Check the NOR controller state */ + hnor->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Program data to NOR memory + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pAddress Device address + * @param pData pointer to the data to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData) +{ + uint32_t deviceaddress; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnor->State == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send program data command */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_PROGRAM); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE(pAddress, NOR_CMD_WORD_PROGRAM); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + if (status != HAL_ERROR) + { + /* Write the data */ + NOR_WRITE(pAddress, *pData); + } + + /* Check the NOR controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Reads a half-word buffer from the NOR memory. + * @param hnor pointer to the NOR handle + * @param uwAddress NOR memory internal address to read from. + * @param pData pointer to the buffer that receives the data read from the + * NOR memory. + * @param uwBufferSize number of Half word to read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_ReadBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData, + uint32_t uwBufferSize) +{ + uint32_t deviceaddress; + uint32_t size = uwBufferSize; + uint32_t address = uwAddress; + uint16_t *data = pData; + HAL_NOR_StateTypeDef state; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + state = hnor->State; + if (state == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_NOR_STATE_PROTECTED) + { + return HAL_ERROR; + } + else if (state == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send read data command */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_READ_RESET); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + if (status != HAL_ERROR) + { + /* Read buffer */ + while (size > 0U) + { + *data = *(__IO uint16_t *)address; + data++; + address += 2U; + size--; + } + } + + /* Check the NOR controller state */ + hnor->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Writes a half-word buffer to the NOR memory. This function must be used + only with S29GL128P NOR memory. + * @param hnor pointer to the NOR handle + * @param uwAddress NOR memory internal start write address + * @param pData pointer to source data buffer. + * @param uwBufferSize Size of the buffer to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_ProgramBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData, + uint32_t uwBufferSize) +{ + uint16_t *p_currentaddress; + const uint16_t *p_endaddress; + uint16_t *data = pData; + uint32_t deviceaddress; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnor->State == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Initialize variables */ + p_currentaddress = (uint16_t *)(deviceaddress + uwAddress); + p_endaddress = (uint16_t *)(deviceaddress + uwAddress + (2U * (uwBufferSize - 1U))); + + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + /* Issue unlock command sequence */ + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + + /* Write Buffer Load Command */ + NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG); + NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U)); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + /* Write Buffer Load Command */ + NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_BUFFERED_PROGRAM); + NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U)); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + if (status != HAL_ERROR) + { + /* Load Data into NOR Buffer */ + while (p_currentaddress <= p_endaddress) + { + NOR_WRITE(p_currentaddress, *data); + + data++; + p_currentaddress ++; + } + + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM); + } + else /* => hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET */ + { + NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_CONFIRM); + } + } + + /* Check the NOR controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; + +} + +/** + * @brief Erase the specified block of the NOR memory + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param BlockAddress Block to erase address + * @param Address Device address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Erase_Block(NOR_HandleTypeDef *hnor, uint32_t BlockAddress, uint32_t Address) +{ + uint32_t deviceaddress; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnor->State == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send block erase command sequence */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH); + NOR_WRITE((uint32_t)(BlockAddress + Address), NOR_CMD_DATA_BLOCK_ERASE); + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_UNLOCK); + NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM); + NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_ERASE); + NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + /* Check the NOR memory status and update the controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; + +} + +/** + * @brief Erase the entire NOR chip. + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param Address Device address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Erase_Chip(NOR_HandleTypeDef *hnor, uint32_t Address) +{ + uint32_t deviceaddress; + HAL_StatusTypeDef status = HAL_OK; + UNUSED(Address); + + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hnor->State == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send NOR chip erase command sequence */ + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH), + NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH); + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SIXTH), NOR_CMD_DATA_CHIP_ERASE); + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_ERROR; + } + + /* Check the NOR memory status and update the controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return status; +} + +/** + * @brief Read NOR flash CFI IDs + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param pNOR_CFI pointer to NOR CFI IDs structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_Read_CFI(NOR_HandleTypeDef *hnor, NOR_CFITypeDef *pNOR_CFI) +{ + uint32_t deviceaddress; + HAL_NOR_StateTypeDef state; + + /* Check the NOR controller state */ + state = hnor->State; + if (state == HAL_NOR_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_NOR_STATE_PROTECTED) + { + return HAL_ERROR; + } + else if (state == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Select the NOR device address */ + if (hnor->Init.NSBank == FMC_NORSRAM_BANK1) + { + deviceaddress = NOR_MEMORY_ADRESS1; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK2) + { + deviceaddress = NOR_MEMORY_ADRESS2; + } + else if (hnor->Init.NSBank == FMC_NORSRAM_BANK3) + { + deviceaddress = NOR_MEMORY_ADRESS3; + } + else /* FMC_NORSRAM_BANK4 */ + { + deviceaddress = NOR_MEMORY_ADRESS4; + } + + /* Send read CFI query command */ + NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI); + + /* read the NOR CFI information */ + pNOR_CFI->CFI_1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI1_ADDRESS); + pNOR_CFI->CFI_2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI2_ADDRESS); + pNOR_CFI->CFI_3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI3_ADDRESS); + pNOR_CFI->CFI_4 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI4_ADDRESS); + + /* Check the NOR controller state */ + hnor->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User NOR Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hnor : NOR handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID + * @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_NOR_RegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId, + pNOR_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_NOR_StateTypeDef state; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hnor); + + state = hnor->State; + if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_NOR_MSP_INIT_CB_ID : + hnor->MspInitCallback = pCallback; + break; + case HAL_NOR_MSP_DEINIT_CB_ID : + hnor->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hnor); + return status; +} + +/** + * @brief Unregister a User NOR Callback + * NOR Callback is redirected to the weak (surcharged) predefined callback + * @param hnor : NOR handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID + * @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_NOR_UnRegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_NOR_StateTypeDef state; + + /* Process locked */ + __HAL_LOCK(hnor); + + state = hnor->State; + if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_NOR_MSP_INIT_CB_ID : + hnor->MspInitCallback = HAL_NOR_MspInit; + break; + case HAL_NOR_MSP_DEINIT_CB_ID : + hnor->MspDeInitCallback = HAL_NOR_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hnor); + return status; +} +#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */ + +/** + * @} + */ + +/** @defgroup NOR_Exported_Functions_Group3 NOR Control functions + * @brief management functions + * +@verbatim + ============================================================================== + ##### NOR Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the NOR interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically NOR write operation. + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_WriteOperation_Enable(NOR_HandleTypeDef *hnor) +{ + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_PROTECTED) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Enable write operation */ + (void)FMC_NORSRAM_WriteOperation_Enable(hnor->Instance, hnor->Init.NSBank); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically NOR write operation. + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_NOR_WriteOperation_Disable(NOR_HandleTypeDef *hnor) +{ + /* Check the NOR controller state */ + if (hnor->State == HAL_NOR_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hnor); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_BUSY; + + /* Disable write operation */ + (void)FMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank); + + /* Update the NOR controller state */ + hnor->State = HAL_NOR_STATE_PROTECTED; + + /* Process unlocked */ + __HAL_UNLOCK(hnor); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup NOR_Exported_Functions_Group4 NOR State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### NOR State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the NOR controller + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief return the NOR controller state + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @retval NOR controller state + */ +HAL_NOR_StateTypeDef HAL_NOR_GetState(NOR_HandleTypeDef *hnor) +{ + return hnor->State; +} + +/** + * @brief Returns the NOR operation status. + * @param hnor pointer to a NOR_HandleTypeDef structure that contains + * the configuration information for NOR module. + * @param Address Device address + * @param Timeout NOR programming Timeout + * @retval NOR_Status The returned value can be: HAL_NOR_STATUS_SUCCESS, HAL_NOR_STATUS_ERROR + * or HAL_NOR_STATUS_TIMEOUT + */ +HAL_NOR_StatusTypeDef HAL_NOR_GetStatus(NOR_HandleTypeDef *hnor, uint32_t Address, uint32_t Timeout) +{ + HAL_NOR_StatusTypeDef status = HAL_NOR_STATUS_ONGOING; + uint16_t tmpsr1; + uint16_t tmpsr2; + uint32_t tickstart; + + /* Poll on NOR memory Ready/Busy signal ------------------------------------*/ + HAL_NOR_MspWait(hnor, Timeout); + + /* Get the NOR memory operation status -------------------------------------*/ + + /* Get tick */ + tickstart = HAL_GetTick(); + + if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET) + { + while ((status != HAL_NOR_STATUS_SUCCESS) && (status != HAL_NOR_STATUS_TIMEOUT)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + status = HAL_NOR_STATUS_TIMEOUT; + } + } + + /* Read NOR status register (DQ6 and DQ5) */ + tmpsr1 = *(__IO uint16_t *)Address; + tmpsr2 = *(__IO uint16_t *)Address; + + /* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */ + if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6)) + { + return HAL_NOR_STATUS_SUCCESS ; + } + + if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5) + { + status = HAL_NOR_STATUS_ONGOING; + } + + tmpsr1 = *(__IO uint16_t *)Address; + tmpsr2 = *(__IO uint16_t *)Address; + + /* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */ + if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6)) + { + return HAL_NOR_STATUS_SUCCESS; + } + if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5) + { + return HAL_NOR_STATUS_ERROR; + } + } + } + else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET) + { + do + { + NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG); + tmpsr2 = *(__IO uint16_t *)(Address); + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_NOR_STATUS_TIMEOUT; + } + } + } while ((tmpsr2 & NOR_MASK_STATUS_DQ7) == 0U); + + NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG); + tmpsr1 = *(__IO uint16_t *)(Address); + if ((tmpsr1 & (NOR_MASK_STATUS_DQ5 | NOR_MASK_STATUS_DQ4)) != 0U) + { + /* Clear the Status Register */ + NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG); + status = HAL_NOR_STATUS_ERROR; + } + else + { + status = HAL_NOR_STATUS_SUCCESS; + } + } + else + { + /* Primary command set not supported by the driver */ + status = HAL_NOR_STATUS_ERROR; + } + + /* Return the operation status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_NOR_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* FMC_Bank1 || FSMC_Bank1 */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c new file mode 100644 index 0000000..14deb47 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pccard.c @@ -0,0 +1,946 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_pccard.c + * @author MCD Application Team + * @brief PCCARD HAL module driver. + * This file provides a generic firmware to drive PCCARD memories mounted + * as external device. + * + ****************************************************************************** + * @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 ##### + =============================================================================== + [..] + This driver is a generic layered driver which contains a set of APIs used to + control PCCARD/compact flash memories. It uses the FMC/FSMC layer functions + to interface with PCCARD devices. This driver is used for: + + (+) PCCARD/Compact Flash memory configuration sequence using the function + HAL_PCCARD_Init()/HAL_CF_Init() with control and timing parameters for + both common and attribute spaces. + + (+) Read PCCARD/Compact Flash memory maker and device IDs using the function + HAL_PCCARD_Read_ID()/HAL_CF_Read_ID(). The read information is stored in + the CompactFlash_ID structure declared by the function caller. + + (+) Access PCCARD/Compact Flash memory by read/write operations using the functions + HAL_PCCARD_Read_Sector()/ HAL_PCCARD_Write_Sector() - + HAL_CF_Read_Sector()/HAL_CF_Write_Sector(), to read/write sector. + + (+) Perform PCCARD/Compact Flash Reset chip operation using the function + HAL_PCCARD_Reset()/HAL_CF_Reset. + + (+) Perform PCCARD/Compact Flash erase sector operation using the function + HAL_PCCARD_Erase_Sector()/HAL_CF_Erase_Sector. + + (+) Read the PCCARD/Compact Flash status operation using the function + HAL_PCCARD_ReadStatus()/HAL_CF_ReadStatus(). + + (+) You can monitor the PCCARD/Compact Flash device HAL state by calling + the function HAL_PCCARD_GetState()/HAL_CF_GetState() + + [..] + (@) This driver is a set of generic APIs which handle standard PCCARD/compact flash + operations. If a PCCARD/Compact Flash device contains different operations + and/or implementations, it should be implemented separately. + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_PCCARD_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) MspInitCallback : PCCARD MspInit. + (+) MspDeInitCallback : PCCARD MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_PCCARD_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) MspInitCallback : PCCARD MspInit. + (+) MspDeInitCallback : PCCARD MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_PCCARD_Init and if the state is HAL_PCCARD_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_PCCARD_Init + and HAL_PCCARD_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_PCCARD_Init and HAL_PCCARD_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_PCCARD_RegisterCallback before calling HAL_PCCARD_DeInit + or HAL_PCCARD_Init function. + + When The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(FMC_Bank4) || defined(FSMC_Bank4) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_PCCARD_MODULE_ENABLED + +/** @defgroup PCCARD PCCARD + * @brief PCCARD HAL module driver + * @{ + */ +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup PCCARD_Private_Defines PCCARD Private Defines + * @{ + */ +#define PCCARD_TIMEOUT_READ_ID 0x0000FFFFU +#define PCCARD_TIMEOUT_READ_WRITE_SECTOR 0x0000FFFFU +#define PCCARD_TIMEOUT_ERASE_SECTOR 0x00000400U +#define PCCARD_TIMEOUT_STATUS 0x01000000U + +#define PCCARD_STATUS_OK (uint8_t)0x58 +#define PCCARD_STATUS_WRITE_OK (uint8_t)0x50 +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function ----------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup PCCARD_Exported_Functions PCCARD Exported Functions + * @{ + */ + +/** @defgroup PCCARD_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### PCCARD Initialization and de-initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize + the PCCARD memory + +@endverbatim + * @{ + */ + +/** + * @brief Perform the PCCARD memory Initialization sequence + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @param ComSpaceTiming Common space timing structure + * @param AttSpaceTiming Attribute space timing structure + * @param IOSpaceTiming IO space timing structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FMC_NAND_PCC_TimingTypeDef *ComSpaceTiming, + FMC_NAND_PCC_TimingTypeDef *AttSpaceTiming, FMC_NAND_PCC_TimingTypeDef *IOSpaceTiming) +{ + /* Check the PCCARD controller state */ + if (hpccard == NULL) + { + return HAL_ERROR; + } + + if (hpccard->State == HAL_PCCARD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hpccard->Lock = HAL_UNLOCKED; +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + if (hpccard->MspInitCallback == NULL) + { + hpccard->MspInitCallback = HAL_PCCARD_MspInit; + } + hpccard->ItCallback = HAL_PCCARD_ITCallback; + + /* Init the low level hardware */ + hpccard->MspInitCallback(hpccard); +#else + /* Initialize the low level hardware (MSP) */ + HAL_PCCARD_MspInit(hpccard); +#endif + } + + /* Initialize the PCCARD state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + /* Initialize PCCARD control Interface */ + FMC_PCCARD_Init(hpccard->Instance, &(hpccard->Init)); + + /* Init PCCARD common space timing Interface */ + FMC_PCCARD_CommonSpace_Timing_Init(hpccard->Instance, ComSpaceTiming); + + /* Init PCCARD attribute space timing Interface */ + FMC_PCCARD_AttributeSpace_Timing_Init(hpccard->Instance, AttSpaceTiming); + + /* Init PCCARD IO space timing Interface */ + FMC_PCCARD_IOSpace_Timing_Init(hpccard->Instance, IOSpaceTiming); + + /* Enable the PCCARD device */ + __FMC_PCCARD_ENABLE(hpccard->Instance); + + /* Update the PCCARD state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + return HAL_OK; + +} + +/** + * @brief Perform the PCCARD memory De-initialization sequence + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard) +{ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + if (hpccard->MspDeInitCallback == NULL) + { + hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit; + } + + /* DeInit the low level hardware */ + hpccard->MspDeInitCallback(hpccard); +#else + /* De-Initialize the low level hardware (MSP) */ + HAL_PCCARD_MspDeInit(hpccard); +#endif + + /* Configure the PCCARD registers with their reset values */ + FMC_PCCARD_DeInit(hpccard->Instance); + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + +/** + * @brief PCCARD MSP Init + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval None + */ +__weak void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpccard); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_PCCARD_MspInit could be implemented in the user file + */ +} + +/** + * @brief PCCARD MSP DeInit + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval None + */ +__weak void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpccard); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_PCCARD_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup PCCARD_Exported_Functions_Group2 Input and Output functions + * @brief Input Output and memory control functions + * + @verbatim + ============================================================================== + ##### PCCARD Input and Output functions ##### + ============================================================================== + [..] + This section provides functions allowing to use and control the PCCARD memory + +@endverbatim + * @{ + */ + +/** + * @brief Read Compact Flash's ID. + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @param CompactFlash_ID Compact flash ID structure. + * @param pStatus pointer to compact flash status + * @retval HAL status + * + */ +HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus) +{ + uint32_t timeout = PCCARD_TIMEOUT_READ_ID, index = 0U; + uint8_t status = 0; + + /* Process Locked */ + __HAL_LOCK(hpccard); + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + /* Initialize the PCCARD status */ + *pStatus = PCCARD_READY; + + /* Send the Identify Command */ + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xECEC; + + /* Read PCCARD IDs and timeout treatment */ + do + { + /* Read the PCCARD status */ + status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + + timeout--; + } while ((status != PCCARD_STATUS_OK) && timeout); + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + else + { + /* Read PCCARD ID bytes */ + for (index = 0U; index < 16U; index++) + { + CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA); + } + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + +/** + * @brief Read sector from PCCARD memory + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @param pBuffer pointer to destination read buffer + * @param SectorAddress Sector address to read + * @param pStatus pointer to PCCARD status + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress, + uint8_t *pStatus) +{ + uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U; + uint8_t status = 0; + + /* Process Locked */ + __HAL_LOCK(hpccard); + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + /* Initialize PCCARD status */ + *pStatus = PCCARD_READY; + + /* Set the parameters to write a sector */ + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000; + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress); + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xE4A0; + + do + { + /* wait till the Status = 0x80 */ + status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } while ((status == 0x80U) && timeout); + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + + timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR; + + do + { + /* wait till the Status = PCCARD_STATUS_OK */ + status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } while ((status != PCCARD_STATUS_OK) && timeout); + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + + /* Read bytes */ + for (; index < PCCARD_SECTOR_SIZE; index++) + { + *(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR); + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + + +/** + * @brief Write sector to PCCARD memory + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @param pBuffer pointer to source write buffer + * @param SectorAddress Sector address to write + * @param pStatus pointer to PCCARD status + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress, + uint8_t *pStatus) +{ + uint32_t timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR, index = 0U; + uint8_t status = 0; + + /* Process Locked */ + __HAL_LOCK(hpccard); + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + /* Initialize PCCARD status */ + *pStatus = PCCARD_READY; + + /* Set the parameters to write a sector */ + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000; + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress); + *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0x30A0; + + do + { + /* Wait till the Status = PCCARD_STATUS_OK */ + status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } while ((status != PCCARD_STATUS_OK) && timeout); + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + + /* Write bytes */ + for (; index < PCCARD_SECTOR_SIZE; index++) + { + *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++; + } + + do + { + /* Wait till the Status = PCCARD_STATUS_WRITE_OK */ + status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } while ((status != PCCARD_STATUS_WRITE_OK) && timeout); + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + + +/** + * @brief Erase sector from PCCARD memory + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @param SectorAddress Sector address to erase + * @param pStatus pointer to PCCARD status + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus) +{ + uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR; + uint8_t status = 0; + + /* Process Locked */ + __HAL_LOCK(hpccard); + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Update the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + /* Initialize PCCARD status */ + *pStatus = PCCARD_READY; + + /* Set the parameters to write a sector */ + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW) = 0x00; + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00; + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress; + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = 0x01; + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD) = 0xA0; + *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = ATA_ERASE_SECTOR_CMD; + + /* wait till the PCCARD is ready */ + status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + + while ((status != PCCARD_STATUS_WRITE_OK) && timeout) + { + status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } + + if (timeout == 0U) + { + *pStatus = PCCARD_TIMEOUT_ERROR; + } + + /* Check the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + +/** + * @brief Reset the PCCARD memory + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard) +{ + /* Process Locked */ + __HAL_LOCK(hpccard); + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_BUSY; + } + + /* Provide a SW reset and Read and verify the: + - PCCard Configuration Option Register at address 0x98000200 --> 0x80 + - Card Configuration and Status Register at address 0x98000202 --> 0x00 + - Pin Replacement Register at address 0x98000204 --> 0x0C + - Socket and Copy Register at address 0x98000206 --> 0x00 + */ + + /* Check the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_BUSY; + + *(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01; + + /* Check the PCCARD controller state */ + hpccard->State = HAL_PCCARD_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hpccard); + + return HAL_OK; +} + +/** + * @brief This function handles PCCARD device interrupt request. + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval HAL status + */ +void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard) +{ + /* Check PCCARD interrupt Rising edge flag */ + if (__FMC_PCCARD_GET_FLAG(hpccard->Instance, FMC_FLAG_RISING_EDGE)) + { + /* PCCARD interrupt callback*/ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + hpccard->ItCallback(hpccard); +#else + HAL_PCCARD_ITCallback(hpccard); +#endif + + /* Clear PCCARD interrupt Rising edge pending bit */ + __FMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FMC_FLAG_RISING_EDGE); + } + + /* Check PCCARD interrupt Level flag */ + if (__FMC_PCCARD_GET_FLAG(hpccard->Instance, FMC_FLAG_LEVEL)) + { + /* PCCARD interrupt callback*/ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + hpccard->ItCallback(hpccard); +#else + HAL_PCCARD_ITCallback(hpccard); +#endif + + /* Clear PCCARD interrupt Level pending bit */ + __FMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FMC_FLAG_LEVEL); + } + + /* Check PCCARD interrupt Falling edge flag */ + if (__FMC_PCCARD_GET_FLAG(hpccard->Instance, FMC_FLAG_FALLING_EDGE)) + { + /* PCCARD interrupt callback*/ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + hpccard->ItCallback(hpccard); +#else + HAL_PCCARD_ITCallback(hpccard); +#endif + + /* Clear PCCARD interrupt Falling edge pending bit */ + __FMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FMC_FLAG_FALLING_EDGE); + } + + /* Check PCCARD interrupt FIFO empty flag */ + if (__FMC_PCCARD_GET_FLAG(hpccard->Instance, FMC_FLAG_FEMPT)) + { + /* PCCARD interrupt callback*/ +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) + hpccard->ItCallback(hpccard); +#else + HAL_PCCARD_ITCallback(hpccard); +#endif + + /* Clear PCCARD interrupt FIFO empty pending bit */ + __FMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FMC_FLAG_FEMPT); + } +} + +/** + * @brief PCCARD interrupt feature callback + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval None + */ +__weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hpccard); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_PCCARD_ITCallback could be implemented in the user file + */ +} + +#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User PCCARD Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hpccard : PCCARD handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID + * @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID + * @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId, + pPCCARD_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hpccard); + + if (hpccard->State == HAL_PCCARD_STATE_READY) + { + switch (CallbackId) + { + case HAL_PCCARD_MSP_INIT_CB_ID : + hpccard->MspInitCallback = pCallback; + break; + case HAL_PCCARD_MSP_DEINIT_CB_ID : + hpccard->MspDeInitCallback = pCallback; + break; + case HAL_PCCARD_IT_CB_ID : + hpccard->ItCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hpccard->State == HAL_PCCARD_STATE_RESET) + { + switch (CallbackId) + { + case HAL_PCCARD_MSP_INIT_CB_ID : + hpccard->MspInitCallback = pCallback; + break; + case HAL_PCCARD_MSP_DEINIT_CB_ID : + hpccard->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hpccard); + return status; +} + +/** + * @brief Unregister a User PCCARD Callback + * PCCARD Callback is redirected to the weak (surcharged) predefined callback + * @param hpccard : PCCARD handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID + * @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID + * @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hpccard); + + if (hpccard->State == HAL_PCCARD_STATE_READY) + { + switch (CallbackId) + { + case HAL_PCCARD_MSP_INIT_CB_ID : + hpccard->MspInitCallback = HAL_PCCARD_MspInit; + break; + case HAL_PCCARD_MSP_DEINIT_CB_ID : + hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit; + break; + case HAL_PCCARD_IT_CB_ID : + hpccard->ItCallback = HAL_PCCARD_ITCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hpccard->State == HAL_PCCARD_STATE_RESET) + { + switch (CallbackId) + { + case HAL_PCCARD_MSP_INIT_CB_ID : + hpccard->MspInitCallback = HAL_PCCARD_MspInit; + break; + case HAL_PCCARD_MSP_DEINIT_CB_ID : + hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hpccard); + return status; +} +#endif + +/** + * @} + */ + +/** @defgroup PCCARD_Exported_Functions_Group3 State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### PCCARD State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the PCCARD controller + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief return the PCCARD controller state + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval HAL state + */ +HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard) +{ + return hpccard->State; +} + +/** + * @brief Get the compact flash memory status + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval New status of the PCCARD operation. This parameter can be: + * - CompactFlash_TIMEOUT_ERROR: when the previous operation generate + * a Timeout error + * - CompactFlash_READY: when memory is ready for the next operation + */ +HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard) +{ + uint32_t timeout = PCCARD_TIMEOUT_STATUS, status_pccard = 0U; + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_PCCARD_STATUS_ONGOING; + } + + status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + + while ((status_pccard == PCCARD_BUSY) && timeout) + { + status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + timeout--; + } + + if (timeout == 0U) + { + status_pccard = PCCARD_TIMEOUT_ERROR; + } + + /* Return the operation status */ + return (HAL_PCCARD_StatusTypeDef) status_pccard; +} + +/** + * @brief Reads the Compact Flash memory status using the Read status command + * @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains + * the configuration information for PCCARD module. + * @retval The status of the Compact Flash memory. This parameter can be: + * - CompactFlash_BUSY: when memory is busy + * - CompactFlash_READY: when memory is ready for the next operation + * - CompactFlash_ERROR: when the previous operation generates error + */ +HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard) +{ + uint8_t data = 0U, status_pccard = PCCARD_BUSY; + + /* Check the PCCARD controller state */ + if (hpccard->State == HAL_PCCARD_STATE_BUSY) + { + return HAL_PCCARD_STATUS_ONGOING; + } + + /* Read status operation */ + data = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE); + + if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR) + { + status_pccard = PCCARD_TIMEOUT_ERROR; + } + else if ((data & PCCARD_READY) == PCCARD_READY) + { + status_pccard = PCCARD_READY; + } + + return (HAL_PCCARD_StatusTypeDef) status_pccard; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_PCCARD_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* FMC_Bank4 || FSMC_Bank4 */ diff --git a/libs/hal/stm32f4xx_hal_pcd.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c similarity index 100% rename from libs/hal/stm32f4xx_hal_pcd.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c diff --git a/libs/hal/stm32f4xx_hal_pcd_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_pcd_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c diff --git a/libs/hal/stm32f4xx_hal_pwr.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c similarity index 99% rename from libs/hal/stm32f4xx_hal_pwr.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c index b4bb483..f5863fa 100644 --- a/libs/hal/stm32f4xx_hal_pwr.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr.c @@ -378,6 +378,9 @@ void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx) */ void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry) { + /* Prevent unused argument(s) compilation warning */ + UNUSED(Regulator); + /* Check the parameters */ assert_param(IS_PWR_REGULATOR(Regulator)); assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry)); diff --git a/libs/hal/stm32f4xx_hal_pwr_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_pwr_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pwr_ex.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c new file mode 100644 index 0000000..a3326f2 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_qspi.c @@ -0,0 +1,2915 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_qspi.c + * @author MCD Application Team + * @brief QSPI HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the QuadSPI interface (QSPI). + * + Initialization and de-initialization functions + * + Indirect functional mode management + * + Memory-mapped functional mode management + * + Auto-polling functional mode management + * + Interrupts and flags management + * + DMA channel configuration for indirect functional mode + * + Errors management and abort functionality + * + * + ****************************************************************************** + * @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 ##### + =============================================================================== + [..] + *** Initialization *** + ====================== + [..] + (#) As prerequisite, fill in the HAL_QSPI_MspInit() : + (++) Enable QuadSPI clock interface with __HAL_RCC_QSPI_CLK_ENABLE(). + (++) Reset QuadSPI Peripheral with __HAL_RCC_QSPI_FORCE_RESET() and __HAL_RCC_QSPI_RELEASE_RESET(). + (++) Enable the clocks for the QuadSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE(). + (++) Configure these QuadSPI pins in alternate mode using HAL_GPIO_Init(). + (++) If interrupt mode is used, enable and configure QuadSPI global + interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + (++) If DMA mode is used, enable the clocks for the QuadSPI DMA channel + with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(), + link it with QuadSPI handle using __HAL_LINKDMA(), enable and configure + DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ(). + (#) Configure the flash size, the clock prescaler, the fifo threshold, the + clock mode, the sample shifting and the CS high time using the HAL_QSPI_Init() function. + + *** Indirect functional mode *** + ================================ + [..] + (#) Configure the command sequence using the HAL_QSPI_Command() or HAL_QSPI_Command_IT() + functions : + (++) Instruction phase : the mode used and if present the instruction opcode. + (++) Address phase : the mode used and if present the size and the address value. + (++) Alternate-bytes phase : the mode used and if present the size and the alternate + bytes values. + (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). + (++) Data phase : the mode used and if present the number of bytes. + (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay + if activated. + (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. + (#) If no data is required for the command, it is sent directly to the memory : + (++) In polling mode, the output of the function is done when the transfer is complete. + (++) In interrupt mode, HAL_QSPI_CmdCpltCallback() will be called when the transfer is complete. + (#) For the indirect write mode, use HAL_QSPI_Transmit(), HAL_QSPI_Transmit_DMA() or + HAL_QSPI_Transmit_IT() after the command configuration : + (++) In polling mode, the output of the function is done when the transfer is complete. + (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold + is reached and HAL_QSPI_TxCpltCallback() will be called when the transfer is complete. + (++) In DMA mode, HAL_QSPI_TxHalfCpltCallback() will be called at the half transfer and + HAL_QSPI_TxCpltCallback() will be called when the transfer is complete. + (#) For the indirect read mode, use HAL_QSPI_Receive(), HAL_QSPI_Receive_DMA() or + HAL_QSPI_Receive_IT() after the command configuration : + (++) In polling mode, the output of the function is done when the transfer is complete. + (++) In interrupt mode, HAL_QSPI_FifoThresholdCallback() will be called when the fifo threshold + is reached and HAL_QSPI_RxCpltCallback() will be called when the transfer is complete. + (++) In DMA mode, HAL_QSPI_RxHalfCpltCallback() will be called at the half transfer and + HAL_QSPI_RxCpltCallback() will be called when the transfer is complete. + + *** Auto-polling functional mode *** + ==================================== + [..] + (#) Configure the command sequence and the auto-polling functional mode using the + HAL_QSPI_AutoPolling() or HAL_QSPI_AutoPolling_IT() functions : + (++) Instruction phase : the mode used and if present the instruction opcode. + (++) Address phase : the mode used and if present the size and the address value. + (++) Alternate-bytes phase : the mode used and if present the size and the alternate + bytes values. + (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). + (++) Data phase : the mode used. + (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay + if activated. + (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. + (++) The size of the status bytes, the match value, the mask used, the match mode (OR/AND), + the polling interval and the automatic stop activation. + (#) After the configuration : + (++) In polling mode, the output of the function is done when the status match is reached. The + automatic stop is activated to avoid an infinite loop. + (++) In interrupt mode, HAL_QSPI_StatusMatchCallback() will be called each time the status match is reached. + + *** Memory-mapped functional mode *** + ===================================== + [..] + (#) Configure the command sequence and the memory-mapped functional mode using the + HAL_QSPI_MemoryMapped() functions : + (++) Instruction phase : the mode used and if present the instruction opcode. + (++) Address phase : the mode used and the size. + (++) Alternate-bytes phase : the mode used and if present the size and the alternate + bytes values. + (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase). + (++) Data phase : the mode used. + (++) Double Data Rate (DDR) mode : the activation (or not) of this mode and the delay + if activated. + (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode. + (++) The timeout activation and the timeout period. + (#) After the configuration, the QuadSPI will be used as soon as an access on the AHB is done on + the address range. HAL_QSPI_TimeOutCallback() will be called when the timeout expires. + + *** Errors management and abort functionality *** + ================================================= + [..] + (#) HAL_QSPI_GetError() function gives the error raised during the last operation. + (#) HAL_QSPI_Abort() and HAL_QSPI_Abort_IT() functions aborts any on-going operation and + flushes the fifo : + (++) In polling mode, the output of the function is done when the transfer + complete bit is set and the busy bit cleared. + (++) In interrupt mode, HAL_QSPI_AbortCpltCallback() will be called when + the transfer complete bit is set. + + *** Control functions *** + ========================= + [..] + (#) HAL_QSPI_GetState() function gives the current state of the HAL QuadSPI driver. + (#) HAL_QSPI_SetTimeout() function configures the timeout value used in the driver. + (#) HAL_QSPI_SetFifoThreshold() function configures the threshold on the Fifo of the QSPI IP. + (#) HAL_QSPI_GetFifoThreshold() function gives the current of the Fifo's threshold + (#) HAL_QSPI_SetFlashID() function configures the index of the flash memory to be accessed. + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_QSPI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_QSPI_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) FifoThresholdCallback : callback when the fifo threshold is reached. + (+) CmdCpltCallback : callback when a command without data is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxHalfCpltCallback : callback when half of the reception transfer is completed. + (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed. + (+) StatusMatchCallback : callback when a status match occurs. + (+) TimeOutCallback : callback when the timeout perioed expires. + (+) MspInitCallback : QSPI MspInit. + (+) MspDeInitCallback : QSPI MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_QSPI_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) FifoThresholdCallback : callback when the fifo threshold is reached. + (+) CmdCpltCallback : callback when a command without data is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxHalfCpltCallback : callback when half of the reception transfer is completed. + (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed. + (+) StatusMatchCallback : callback when a status match occurs. + (+) TimeOutCallback : callback when the timeout perioed expires. + (+) MspInitCallback : QSPI MspInit. + (+) MspDeInitCallback : QSPI MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_QSPI_Init and if the state is HAL_QSPI_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_QSPI_Init + and HAL_QSPI_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_QSPI_Init and HAL_QSPI_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_QSPI_RegisterCallback before calling HAL_QSPI_DeInit + or HAL_QSPI_Init function. + + When The compilation define USE_HAL_QSPI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + *** Workarounds linked to Silicon Limitation *** + ==================================================== + [..] + (#) Workarounds Implemented inside HAL Driver + (++) Extra data written in the FIFO at the end of a read transfer + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(QUADSPI) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup QSPI QSPI + * @brief QSPI HAL module driver + * @{ + */ +#ifdef HAL_QSPI_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ + +/* Private define ------------------------------------------------------------*/ +/** @defgroup QSPI_Private_Constants QSPI Private Constants + * @{ + */ +#define QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE 0x00000000U /*!Instance)); + assert_param(IS_QSPI_CLOCK_PRESCALER(hqspi->Init.ClockPrescaler)); + assert_param(IS_QSPI_FIFO_THRESHOLD(hqspi->Init.FifoThreshold)); + assert_param(IS_QSPI_SSHIFT(hqspi->Init.SampleShifting)); + assert_param(IS_QSPI_FLASH_SIZE(hqspi->Init.FlashSize)); + assert_param(IS_QSPI_CS_HIGH_TIME(hqspi->Init.ChipSelectHighTime)); + assert_param(IS_QSPI_CLOCK_MODE(hqspi->Init.ClockMode)); + assert_param(IS_QSPI_DUAL_FLASH_MODE(hqspi->Init.DualFlash)); + + if (hqspi->Init.DualFlash != QSPI_DUALFLASH_ENABLE ) + { + assert_param(IS_QSPI_FLASH_ID(hqspi->Init.FlashID)); + } + + if(hqspi->State == HAL_QSPI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hqspi->Lock = HAL_UNLOCKED; + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + /* Reset Callback pointers in HAL_QSPI_STATE_RESET only */ + hqspi->ErrorCallback = HAL_QSPI_ErrorCallback; + hqspi->AbortCpltCallback = HAL_QSPI_AbortCpltCallback; + hqspi->FifoThresholdCallback = HAL_QSPI_FifoThresholdCallback; + hqspi->CmdCpltCallback = HAL_QSPI_CmdCpltCallback; + hqspi->RxCpltCallback = HAL_QSPI_RxCpltCallback; + hqspi->TxCpltCallback = HAL_QSPI_TxCpltCallback; + hqspi->RxHalfCpltCallback = HAL_QSPI_RxHalfCpltCallback; + hqspi->TxHalfCpltCallback = HAL_QSPI_TxHalfCpltCallback; + hqspi->StatusMatchCallback = HAL_QSPI_StatusMatchCallback; + hqspi->TimeOutCallback = HAL_QSPI_TimeOutCallback; + + if(hqspi->MspInitCallback == NULL) + { + hqspi->MspInitCallback = HAL_QSPI_MspInit; + } + + /* Init the low level hardware */ + hqspi->MspInitCallback(hqspi); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_QSPI_MspInit(hqspi); +#endif + + /* Configure the default timeout for the QSPI memory access */ + HAL_QSPI_SetTimeout(hqspi, HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + } + + /* Configure QSPI FIFO Threshold */ + MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES, + ((hqspi->Init.FifoThreshold - 1U) << QUADSPI_CR_FTHRES_Pos)); + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); + + if(status == HAL_OK) + { + /* Configure QSPI Clock Prescaler and Sample Shift */ + MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PRESCALER | QUADSPI_CR_SSHIFT | QUADSPI_CR_FSEL | QUADSPI_CR_DFM), + ((hqspi->Init.ClockPrescaler << QUADSPI_CR_PRESCALER_Pos) | + hqspi->Init.SampleShifting | hqspi->Init.FlashID | hqspi->Init.DualFlash)); + + /* Configure QSPI Flash Size, CS High Time and Clock Mode */ + MODIFY_REG(hqspi->Instance->DCR, (QUADSPI_DCR_FSIZE | QUADSPI_DCR_CSHT | QUADSPI_DCR_CKMODE), + ((hqspi->Init.FlashSize << QUADSPI_DCR_FSIZE_Pos) | + hqspi->Init.ChipSelectHighTime | hqspi->Init.ClockMode)); + + /* Enable the QSPI peripheral */ + __HAL_QSPI_ENABLE(hqspi); + + /* Set QSPI error code to none */ + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Initialize the QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + + /* Release Lock */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** + * @brief De-Initialize the QSPI peripheral. + * @param hqspi QSPI handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_DeInit(QSPI_HandleTypeDef *hqspi) +{ + /* Check the QSPI handle allocation */ + if(hqspi == NULL) + { + return HAL_ERROR; + } + + /* Disable the QSPI Peripheral Clock */ + __HAL_QSPI_DISABLE(hqspi); + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + if(hqspi->MspDeInitCallback == NULL) + { + hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit; + } + + /* DeInit the low level hardware */ + hqspi->MspDeInitCallback(hqspi); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + HAL_QSPI_MspDeInit(hqspi); +#endif + + /* Set QSPI error code to none */ + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Initialize the QSPI state */ + hqspi->State = HAL_QSPI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hqspi); + + return HAL_OK; +} + +/** + * @brief Initialize the QSPI MSP. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_MspInit(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_MspInit can be implemented in the user file + */ +} + +/** + * @brief DeInitialize the QSPI MSP. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_MspDeInit can be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup QSPI_Exported_Functions_Group2 Input and Output operation functions + * @brief QSPI Transmit/Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Handle the interrupts. + (+) Handle the command sequence. + (+) Transmit data in blocking, interrupt or DMA mode. + (+) Receive data in blocking, interrupt or DMA mode. + (+) Manage the auto-polling functional mode. + (+) Manage the memory-mapped functional mode. + +@endverbatim + * @{ + */ + +/** + * @brief Handle QSPI interrupt request. + * @param hqspi QSPI handle + * @retval None + */ +void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi) +{ + __IO uint32_t *data_reg; + uint32_t flag = READ_REG(hqspi->Instance->SR); + uint32_t itsource = READ_REG(hqspi->Instance->CR); + + /* QSPI Fifo Threshold interrupt occurred ----------------------------------*/ + if(((flag & QSPI_FLAG_FT) != 0U) && ((itsource & QSPI_IT_FT) != 0U)) + { + data_reg = &hqspi->Instance->DR; + + if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX) + { + /* Transmission process */ + while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != RESET) + { + if (hqspi->TxXferCount > 0U) + { + /* Fill the FIFO until the threshold is reached */ + *((__IO uint8_t *)data_reg) = *hqspi->pTxBuffPtr; + hqspi->pTxBuffPtr++; + hqspi->TxXferCount--; + } + else + { + /* No more data available for the transfer */ + /* Disable the QSPI FIFO Threshold Interrupt */ + __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT); + break; + } + } + } + else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX) + { + /* Receiving Process */ + while(__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_FT) != RESET) + { + if (hqspi->RxXferCount > 0U) + { + /* Read the FIFO until the threshold is reached */ + *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg); + hqspi->pRxBuffPtr++; + hqspi->RxXferCount--; + } + else + { + /* All data have been received for the transfer */ + /* Disable the QSPI FIFO Threshold Interrupt */ + __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_FT); + break; + } + } + } + else + { + /* Nothing to do */ + } + + /* FIFO Threshold callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->FifoThresholdCallback(hqspi); +#else + HAL_QSPI_FifoThresholdCallback(hqspi); +#endif + } + + /* QSPI Transfer Complete interrupt occurred -------------------------------*/ + else if(((flag & QSPI_FLAG_TC) != 0U) && ((itsource & QSPI_IT_TC) != 0U)) + { + /* Clear interrupt */ + WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TC); + + /* Disable the QSPI FIFO Threshold, Transfer Error and Transfer complete Interrupts */ + __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT); + + /* Transfer complete callback */ + if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_TX) + { + if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hqspi->hdma); + } + + /* Clear Busy bit */ + HAL_QSPI_Abort_IT(hqspi); + + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* TX Complete callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->TxCpltCallback(hqspi); +#else + HAL_QSPI_TxCpltCallback(hqspi); +#endif + } + else if(hqspi->State == HAL_QSPI_STATE_BUSY_INDIRECT_RX) + { + if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hqspi->hdma); + } + else + { + data_reg = &hqspi->Instance->DR; + while(READ_BIT(hqspi->Instance->SR, QUADSPI_SR_FLEVEL) != 0U) + { + if (hqspi->RxXferCount > 0U) + { + /* Read the last data received in the FIFO until it is empty */ + *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg); + hqspi->pRxBuffPtr++; + hqspi->RxXferCount--; + } + else + { + /* All data have been received for the transfer */ + break; + } + } + } + + /* Workaround - Extra data written in the FIFO at the end of a read transfer */ + HAL_QSPI_Abort_IT(hqspi); + + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* RX Complete callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->RxCpltCallback(hqspi); +#else + HAL_QSPI_RxCpltCallback(hqspi); +#endif + } + else if(hqspi->State == HAL_QSPI_STATE_BUSY) + { + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Command Complete callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->CmdCpltCallback(hqspi); +#else + HAL_QSPI_CmdCpltCallback(hqspi); +#endif + } + else if(hqspi->State == HAL_QSPI_STATE_ABORT) + { + /* Reset functional mode configuration to indirect write mode by default */ + CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FMODE); + + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + if (hqspi->ErrorCode == HAL_QSPI_ERROR_NONE) + { + /* Abort called by the user */ + + /* Abort Complete callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->AbortCpltCallback(hqspi); +#else + HAL_QSPI_AbortCpltCallback(hqspi); +#endif + } + else + { + /* Abort due to an error (eg : DMA error) */ + + /* Error callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->ErrorCallback(hqspi); +#else + HAL_QSPI_ErrorCallback(hqspi); +#endif + } + } + else + { + /* Nothing to do */ + } + } + + /* QSPI Status Match interrupt occurred ------------------------------------*/ + else if(((flag & QSPI_FLAG_SM) != 0U) && ((itsource & QSPI_IT_SM) != 0U)) + { + /* Clear interrupt */ + WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_SM); + + /* Check if the automatic poll mode stop is activated */ + if(READ_BIT(hqspi->Instance->CR, QUADSPI_CR_APMS) != 0U) + { + /* Disable the QSPI Transfer Error and Status Match Interrupts */ + __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE)); + + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + } + + /* Status match callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->StatusMatchCallback(hqspi); +#else + HAL_QSPI_StatusMatchCallback(hqspi); +#endif + } + + /* QSPI Transfer Error interrupt occurred ----------------------------------*/ + else if(((flag & QSPI_FLAG_TE) != 0U) && ((itsource & QSPI_IT_TE) != 0U)) + { + /* Clear interrupt */ + WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TE); + + /* Disable all the QSPI Interrupts */ + __HAL_QSPI_DISABLE_IT(hqspi, QSPI_IT_SM | QSPI_IT_TC | QSPI_IT_TE | QSPI_IT_FT); + + /* Set error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_TRANSFER; + + if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Disable the DMA channel */ + hqspi->hdma->XferAbortCallback = QSPI_DMAAbortCplt; + if (HAL_DMA_Abort_IT(hqspi->hdma) != HAL_OK) + { + /* Set error code to DMA */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Error callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->ErrorCallback(hqspi); +#else + HAL_QSPI_ErrorCallback(hqspi); +#endif + } + } + else + { + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Error callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->ErrorCallback(hqspi); +#else + HAL_QSPI_ErrorCallback(hqspi); +#endif + } + } + + /* QSPI Timeout interrupt occurred -----------------------------------------*/ + else if(((flag & QSPI_FLAG_TO) != 0U) && ((itsource & QSPI_IT_TO) != 0U)) + { + /* Clear interrupt */ + WRITE_REG(hqspi->Instance->FCR, QSPI_FLAG_TO); + + /* Timeout callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->TimeOutCallback(hqspi); +#else + HAL_QSPI_TimeOutCallback(hqspi); +#endif + } + + else + { + /* Nothing to do */ + } +} + +/** + * @brief Set the command configuration. + * @param hqspi QSPI handle + * @param cmd : structure that contains the command configuration information + * @param Timeout Timeout duration + * @note This function is used only in Indirect Read or Write Modes + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Command(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); + } + + assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); + } + + assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); + } + + assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); + assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); + + assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); + assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); + assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_BUSY; + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Call the configuration function */ + QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + if (cmd->DataMode == QSPI_DATA_NONE) + { + /* When there is no data phase, the transfer start as soon as the configuration is done + so wait until TC flag is set to go back in idle state */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + else + { + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** + * @brief Set the command configuration in interrupt mode. + * @param hqspi QSPI handle + * @param cmd structure that contains the command configuration information + * @note This function is used only in Indirect Read or Write Modes + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Command_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd) +{ + HAL_StatusTypeDef status; + + /* Check the parameters */ + assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); + } + + assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); + } + + assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); + } + + assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); + assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); + + assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); + assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); + assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_BUSY; + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout_CPUCycle(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout); + + if (status == HAL_OK) + { + if (cmd->DataMode == QSPI_DATA_NONE) + { + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); + } + + /* Call the configuration function */ + QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + if (cmd->DataMode == QSPI_DATA_NONE) + { + /* When there is no data phase, the transfer start as soon as the configuration is done + so activate TC and TE interrupts */ + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI Transfer Error Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_TC); + } + else + { + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + /* Return function status */ + return status; +} + +/** + * @brief Transmit an amount of data in blocking mode. + * @param hqspi QSPI handle + * @param pData pointer to data buffer + * @param Timeout Timeout duration + * @note This function is used only in Indirect Write Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Transmit(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = HAL_GetTick(); + __IO uint32_t *data_reg = &hqspi->Instance->DR; + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; + + /* Configure counters and size of the handle */ + hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->pTxBuffPtr = pData; + + /* Configure QSPI: CCR register with functional as indirect write */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + while(hqspi->TxXferCount > 0U) + { + /* Wait until FT flag is set to send data */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_FT, SET, tickstart, Timeout); + + if (status != HAL_OK) + { + break; + } + + *((__IO uint8_t *)data_reg) = *hqspi->pTxBuffPtr; + hqspi->pTxBuffPtr++; + hqspi->TxXferCount--; + } + + if (status == HAL_OK) + { + /* Wait until TC flag is set to go back in idle state */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Clear Transfer Complete bit */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Clear Busy bit */ + status = HAL_QSPI_Abort(hqspi); + } + } + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + return status; +} + + +/** + * @brief Receive an amount of data in blocking mode. + * @param hqspi QSPI handle + * @param pData pointer to data buffer + * @param Timeout Timeout duration + * @note This function is used only in Indirect Read Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Receive(QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = HAL_GetTick(); + uint32_t addr_reg = READ_REG(hqspi->Instance->AR); + __IO uint32_t *data_reg = &hqspi->Instance->DR; + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; + + /* Configure counters and size of the handle */ + hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->pRxBuffPtr = pData; + + /* Configure QSPI: CCR register with functional as indirect read */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Start the transfer by re-writing the address in AR register */ + WRITE_REG(hqspi->Instance->AR, addr_reg); + + while(hqspi->RxXferCount > 0U) + { + /* Wait until FT or TC flag is set to read received data */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, (QSPI_FLAG_FT | QSPI_FLAG_TC), SET, tickstart, Timeout); + + if (status != HAL_OK) + { + break; + } + + *hqspi->pRxBuffPtr = *((__IO uint8_t *)data_reg); + hqspi->pRxBuffPtr++; + hqspi->RxXferCount--; + } + + if (status == HAL_OK) + { + /* Wait until TC flag is set to go back in idle state */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Clear Transfer Complete bit */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Workaround - Extra data written in the FIFO at the end of a read transfer */ + status = HAL_QSPI_Abort(hqspi); + } + } + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + } + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + return status; +} + +/** + * @brief Send an amount of data in non-blocking mode with interrupt. + * @param hqspi QSPI handle + * @param pData pointer to data buffer + * @note This function is used only in Indirect Write Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Transmit_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; + + /* Configure counters and size of the handle */ + hqspi->TxXferCount = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->TxXferSize = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->pTxBuffPtr = pData; + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); + + /* Configure QSPI: CCR register with functional as indirect write */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC); + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + return status; +} + +/** + * @brief Receive an amount of data in non-blocking mode with interrupt. + * @param hqspi QSPI handle + * @param pData pointer to data buffer + * @note This function is used only in Indirect Read Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Receive_IT(QSPI_HandleTypeDef *hqspi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t addr_reg = READ_REG(hqspi->Instance->AR); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; + + /* Configure counters and size of the handle */ + hqspi->RxXferCount = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->RxXferSize = READ_REG(hqspi->Instance->DLR) + 1U; + hqspi->pRxBuffPtr = pData; + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_TC); + + /* Configure QSPI: CCR register with functional as indirect read */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Start the transfer by re-writing the address in AR register */ + WRITE_REG(hqspi->Instance->AR, addr_reg); + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI transfer error, FIFO threshold and transfer complete Interrupts */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE | QSPI_IT_FT | QSPI_IT_TC); + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + return status; +} + +/** + * @brief Send an amount of data in non-blocking mode with DMA. + * @param hqspi QSPI handle + * @param pData pointer to data buffer + * @note This function is used only in Indirect Write Mode + * @note If DMA peripheral access is configured as halfword, the number + * of data and the fifo threshold should be aligned on halfword + * @note If DMA peripheral access is configured as word, the number + * of data and the fifo threshold should be aligned on word + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Transmit_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1U); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + /* Clear the error code */ + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Configure counters of the handle */ + if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) + { + hqspi->TxXferCount = data_size; + } + else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) + { + if (((data_size % 2U) != 0U) || ((hqspi->Init.FifoThreshold % 2U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on halfword + => no transfer possible with DMA peripheral access configured as halfword */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + else + { + hqspi->TxXferCount = (data_size >> 1U); + } + } + else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) + { + if (((data_size % 4U) != 0U) || ((hqspi->Init.FifoThreshold % 4U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on word + => no transfer possible with DMA peripheral access configured as word */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + else + { + hqspi->TxXferCount = (data_size >> 2U); + } + } + else + { + /* Nothing to do */ + } + + if (status == HAL_OK) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_TX; + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC)); + + /* Configure size and pointer of the handle */ + hqspi->TxXferSize = hqspi->TxXferCount; + hqspi->pTxBuffPtr = pData; + + /* Configure QSPI: CCR register with functional mode as indirect write */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE); + + /* Set the QSPI DMA transfer complete callback */ + hqspi->hdma->XferCpltCallback = QSPI_DMATxCplt; + + /* Set the QSPI DMA Half transfer complete callback */ + hqspi->hdma->XferHalfCpltCallback = QSPI_DMATxHalfCplt; + + /* Set the DMA error callback */ + hqspi->hdma->XferErrorCallback = QSPI_DMAError; + + /* Clear the DMA abort callback */ + hqspi->hdma->XferAbortCallback = NULL; + +#if defined (QSPI1_V2_1L) + /* Bug "ES0305 section 2.1.8 In some specific cases, DMA2 data corruption occurs when managing + AHB and APB2 peripherals in a concurrent way" Workaround Implementation: + Change the following configuration of DMA peripheral + - Enable peripheral increment + - Disable memory increment + - Set DMA direction as peripheral to memory mode */ + + /* Enable peripheral increment mode of the DMA */ + hqspi->hdma->Init.PeriphInc = DMA_PINC_ENABLE; + + /* Disable memory increment mode of the DMA */ + hqspi->hdma->Init.MemInc = DMA_MINC_DISABLE; + + /* Update peripheral/memory increment mode bits */ + MODIFY_REG(hqspi->hdma->Instance->CR, (DMA_SxCR_MINC | DMA_SxCR_PINC), (hqspi->hdma->Init.MemInc | hqspi->hdma->Init.PeriphInc)); + + /* Configure the direction of the DMA */ + hqspi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; +#else + /* Configure the direction of the DMA */ + hqspi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; +#endif /* QSPI1_V2_1L */ + + /* Update direction mode bit */ + MODIFY_REG(hqspi->hdma->Instance->CR, DMA_SxCR_DIR, hqspi->hdma->Init.Direction); + + /* Enable the QSPI transmit DMA Channel */ + if (HAL_DMA_Start_IT(hqspi->hdma, (uint32_t)pData, (uint32_t)&hqspi->Instance->DR, hqspi->TxXferSize) == HAL_OK) + { + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI transfer error Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE); + + /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + } + else + { + status = HAL_ERROR; + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + hqspi->State = HAL_QSPI_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + return status; +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA. + * @param hqspi QSPI handle + * @param pData pointer to data buffer. + * @note This function is used only in Indirect Read Mode + * @note If DMA peripheral access is configured as halfword, the number + * of data and the fifo threshold should be aligned on halfword + * @note If DMA peripheral access is configured as word, the number + * of data and the fifo threshold should be aligned on word + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_Receive_DMA(QSPI_HandleTypeDef *hqspi, uint8_t *pData) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t addr_reg = READ_REG(hqspi->Instance->AR); + uint32_t data_size = (READ_REG(hqspi->Instance->DLR) + 1U); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + /* Clear the error code */ + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + if(pData != NULL ) + { + /* Configure counters of the handle */ + if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE) + { + hqspi->RxXferCount = data_size; + } + else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD) + { + if (((data_size % 2U) != 0U) || ((hqspi->Init.FifoThreshold % 2U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on halfword + => no transfer possible with DMA peripheral access configured as halfword */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + else + { + hqspi->RxXferCount = (data_size >> 1U); + } + } + else if (hqspi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD) + { + if (((data_size % 4U) != 0U) || ((hqspi->Init.FifoThreshold % 4U) != 0U)) + { + /* The number of data or the fifo threshold is not aligned on word + => no transfer possible with DMA peripheral access configured as word */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + else + { + hqspi->RxXferCount = (data_size >> 2U); + } + } + else + { + /* Nothing to do */ + } + + if (status == HAL_OK) + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_INDIRECT_RX; + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, (QSPI_FLAG_TE | QSPI_FLAG_TC)); + + /* Configure size and pointer of the handle */ + hqspi->RxXferSize = hqspi->RxXferCount; + hqspi->pRxBuffPtr = pData; + + /* Set the QSPI DMA transfer complete callback */ + hqspi->hdma->XferCpltCallback = QSPI_DMARxCplt; + + /* Set the QSPI DMA Half transfer complete callback */ + hqspi->hdma->XferHalfCpltCallback = QSPI_DMARxHalfCplt; + + /* Set the DMA error callback */ + hqspi->hdma->XferErrorCallback = QSPI_DMAError; + + /* Clear the DMA abort callback */ + hqspi->hdma->XferAbortCallback = NULL; + +#if defined (QSPI1_V2_1L) + /* Bug "ES0305 section 2.1.8 In some specific cases, DMA2 data corruption occurs when managing + AHB and APB2 peripherals in a concurrent way" Workaround Implementation: + Change the following configuration of DMA peripheral + - Enable peripheral increment + - Disable memory increment + - Set DMA direction as memory to peripheral mode + - 4 Extra words (32-bits) are added for read operation to guarantee + the last data is transferred from DMA FIFO to RAM memory */ + + /* Enable peripheral increment of the DMA */ + hqspi->hdma->Init.PeriphInc = DMA_PINC_ENABLE; + + /* Disable memory increment of the DMA */ + hqspi->hdma->Init.MemInc = DMA_MINC_DISABLE; + + /* Update peripheral/memory increment mode bits */ + MODIFY_REG(hqspi->hdma->Instance->CR, (DMA_SxCR_MINC | DMA_SxCR_PINC), (hqspi->hdma->Init.MemInc | hqspi->hdma->Init.PeriphInc)); + + /* Configure the direction of the DMA */ + hqspi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; + + /* 4 Extra words (32-bits) are needed for read operation to guarantee + the last data is transferred from DMA FIFO to RAM memory */ + WRITE_REG(hqspi->Instance->DLR, (data_size - 1U + 16U)); + + /* Update direction mode bit */ + MODIFY_REG(hqspi->hdma->Instance->CR, DMA_SxCR_DIR, hqspi->hdma->Init.Direction); + + /* Configure QSPI: CCR register with functional as indirect read */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Start the transfer by re-writing the address in AR register */ + WRITE_REG(hqspi->Instance->AR, addr_reg); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hqspi->hdma, (uint32_t)&hqspi->Instance->DR, (uint32_t)pData, hqspi->RxXferSize) == HAL_OK) + { + /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI transfer error Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE); + } + else + { + status = HAL_ERROR; + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + hqspi->State = HAL_QSPI_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } +#else + /* Configure the direction of the DMA */ + hqspi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; + + /* Update direction mode bit */ + MODIFY_REG(hqspi->hdma->Instance->CR, DMA_SxCR_DIR, hqspi->hdma->Init.Direction); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hqspi->hdma, (uint32_t)&hqspi->Instance->DR, (uint32_t)pData, hqspi->RxXferSize)== HAL_OK) + { + /* Configure QSPI: CCR register with functional as indirect read */ + MODIFY_REG(hqspi->Instance->CCR, QUADSPI_CCR_FMODE, QSPI_FUNCTIONAL_MODE_INDIRECT_READ); + + /* Start the transfer by re-writing the address in AR register */ + WRITE_REG(hqspi->Instance->AR, addr_reg); + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI transfer error Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TE); + + /* Enable the DMA transfer by setting the DMAEN bit in the QSPI CR register */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + } + else + { + status = HAL_ERROR; + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + hqspi->State = HAL_QSPI_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } +#endif /* QSPI1_V2_1L */ + } + } + else + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_PARAM; + status = HAL_ERROR; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + return status; +} + +/** + * @brief Configure the QSPI Automatic Polling Mode in blocking mode. + * @param hqspi QSPI handle + * @param cmd structure that contains the command configuration information. + * @param cfg structure that contains the polling configuration information. + * @param Timeout Timeout duration + * @note This function is used only in Automatic Polling Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_AutoPolling(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); + } + + assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); + } + + assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); + } + + assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); + assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); + + assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); + assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); + assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); + + assert_param(IS_QSPI_INTERVAL(cfg->Interval)); + assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize)); + assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING; + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, Timeout); + + if (status == HAL_OK) + { + /* Configure QSPI: PSMAR register with the status match value */ + WRITE_REG(hqspi->Instance->PSMAR, cfg->Match); + + /* Configure QSPI: PSMKR register with the status mask value */ + WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask); + + /* Configure QSPI: PIR register with the interval value */ + WRITE_REG(hqspi->Instance->PIR, cfg->Interval); + + /* Configure QSPI: CR register with Match mode and Automatic stop enabled + (otherwise there will be an infinite loop in blocking mode) */ + MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS), + (cfg->MatchMode | QSPI_AUTOMATIC_STOP_ENABLE)); + + /* Call the configuration function */ + cmd->NbData = cfg->StatusBytesSize; + QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING); + + /* Wait until SM flag is set to go back in idle state */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_SM, SET, tickstart, Timeout); + + if (status == HAL_OK) + { + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_SM); + + /* Update state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** + * @brief Configure the QSPI Automatic Polling Mode in non-blocking mode. + * @param hqspi QSPI handle + * @param cmd structure that contains the command configuration information. + * @param cfg structure that contains the polling configuration information. + * @note This function is used only in Automatic Polling Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg) +{ + HAL_StatusTypeDef status; + + /* Check the parameters */ + assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); + } + + assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); + } + + assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); + } + + assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); + assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); + + assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); + assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); + assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); + + assert_param(IS_QSPI_INTERVAL(cfg->Interval)); + assert_param(IS_QSPI_STATUS_BYTES_SIZE(cfg->StatusBytesSize)); + assert_param(IS_QSPI_MATCH_MODE(cfg->MatchMode)); + assert_param(IS_QSPI_AUTOMATIC_STOP(cfg->AutomaticStop)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_AUTO_POLLING; + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout_CPUCycle(hqspi, QSPI_FLAG_BUSY, RESET, hqspi->Timeout); + + if (status == HAL_OK) + { + /* Configure QSPI: PSMAR register with the status match value */ + WRITE_REG(hqspi->Instance->PSMAR, cfg->Match); + + /* Configure QSPI: PSMKR register with the status mask value */ + WRITE_REG(hqspi->Instance->PSMKR, cfg->Mask); + + /* Configure QSPI: PIR register with the interval value */ + WRITE_REG(hqspi->Instance->PIR, cfg->Interval); + + /* Configure QSPI: CR register with Match mode and Automatic stop mode */ + MODIFY_REG(hqspi->Instance->CR, (QUADSPI_CR_PMM | QUADSPI_CR_APMS), + (cfg->MatchMode | cfg->AutomaticStop)); + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TE | QSPI_FLAG_SM); + + /* Call the configuration function */ + cmd->NbData = cfg->StatusBytesSize; + QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_AUTO_POLLING); + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Enable the QSPI Transfer Error and status match Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, (QSPI_IT_SM | QSPI_IT_TE)); + + } + else + { + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + } + else + { + status = HAL_BUSY; + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + } + + /* Return function status */ + return status; +} + +/** + * @brief Configure the Memory Mapped mode. + * @param hqspi QSPI handle + * @param cmd structure that contains the command configuration information. + * @param cfg structure that contains the memory mapped configuration information. + * @note This function is used only in Memory mapped Mode + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg) +{ + HAL_StatusTypeDef status; + uint32_t tickstart = HAL_GetTick(); + + /* Check the parameters */ + assert_param(IS_QSPI_INSTRUCTION_MODE(cmd->InstructionMode)); + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + assert_param(IS_QSPI_INSTRUCTION(cmd->Instruction)); + } + + assert_param(IS_QSPI_ADDRESS_MODE(cmd->AddressMode)); + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + assert_param(IS_QSPI_ADDRESS_SIZE(cmd->AddressSize)); + } + + assert_param(IS_QSPI_ALTERNATE_BYTES_MODE(cmd->AlternateByteMode)); + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + assert_param(IS_QSPI_ALTERNATE_BYTES_SIZE(cmd->AlternateBytesSize)); + } + + assert_param(IS_QSPI_DUMMY_CYCLES(cmd->DummyCycles)); + assert_param(IS_QSPI_DATA_MODE(cmd->DataMode)); + + assert_param(IS_QSPI_DDR_MODE(cmd->DdrMode)); + assert_param(IS_QSPI_DDR_HHC(cmd->DdrHoldHalfCycle)); + assert_param(IS_QSPI_SIOO_MODE(cmd->SIOOMode)); + + assert_param(IS_QSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + hqspi->ErrorCode = HAL_QSPI_ERROR_NONE; + + /* Update state */ + hqspi->State = HAL_QSPI_STATE_BUSY_MEM_MAPPED; + + /* Wait till BUSY flag reset */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); + + if (status == HAL_OK) + { + /* Configure QSPI: CR register with timeout counter enable */ + MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_TCEN, cfg->TimeOutActivation); + + if (cfg->TimeOutActivation == QSPI_TIMEOUT_COUNTER_ENABLE) + { + assert_param(IS_QSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod)); + + /* Configure QSPI: LPTR register with the low-power timeout value */ + WRITE_REG(hqspi->Instance->LPTR, cfg->TimeOutPeriod); + + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TO); + + /* Enable the QSPI TimeOut Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TO); + } + + /* Call the configuration function */ + QSPI_Config(hqspi, cmd, QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED); + } + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** + * @brief Transfer Error callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_ErrorCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Abort completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_AbortCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Command completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_CmdCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_CmdCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_RxCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Transfer completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_TxCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_RxHalfCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_TxHalfCpltCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_QSPI_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief FIFO Threshold callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_FIFOThresholdCallback could be implemented in the user file + */ +} + +/** + * @brief Status Match callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_StatusMatchCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_StatusMatchCallback could be implemented in the user file + */ +} + +/** + * @brief Timeout callback. + * @param hqspi QSPI handle + * @retval None + */ +__weak void HAL_QSPI_TimeOutCallback(QSPI_HandleTypeDef *hqspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hqspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_QSPI_TimeOutCallback could be implemented in the user file + */ +} +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User QSPI Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hqspi QSPI handle + * @param CallbackId ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_QSPI_ERROR_CB_ID QSPI Error Callback ID + * @arg @ref HAL_QSPI_ABORT_CB_ID QSPI Abort Callback ID + * @arg @ref HAL_QSPI_FIFO_THRESHOLD_CB_ID QSPI FIFO Threshold Callback ID + * @arg @ref HAL_QSPI_CMD_CPLT_CB_ID QSPI Command Complete Callback ID + * @arg @ref HAL_QSPI_RX_CPLT_CB_ID QSPI Rx Complete Callback ID + * @arg @ref HAL_QSPI_TX_CPLT_CB_ID QSPI Tx Complete Callback ID + * @arg @ref HAL_QSPI_RX_HALF_CPLT_CB_ID QSPI Rx Half Complete Callback ID + * @arg @ref HAL_QSPI_TX_HALF_CPLT_CB_ID QSPI Tx Half Complete Callback ID + * @arg @ref HAL_QSPI_STATUS_MATCH_CB_ID QSPI Status Match Callback ID + * @arg @ref HAL_QSPI_TIMEOUT_CB_ID QSPI Timeout Callback ID + * @arg @ref HAL_QSPI_MSP_INIT_CB_ID QSPI MspInit callback ID + * @arg @ref HAL_QSPI_MSP_DEINIT_CB_ID QSPI MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_QSPI_RegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId, pQSPI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + switch (CallbackId) + { + case HAL_QSPI_ERROR_CB_ID : + hqspi->ErrorCallback = pCallback; + break; + case HAL_QSPI_ABORT_CB_ID : + hqspi->AbortCpltCallback = pCallback; + break; + case HAL_QSPI_FIFO_THRESHOLD_CB_ID : + hqspi->FifoThresholdCallback = pCallback; + break; + case HAL_QSPI_CMD_CPLT_CB_ID : + hqspi->CmdCpltCallback = pCallback; + break; + case HAL_QSPI_RX_CPLT_CB_ID : + hqspi->RxCpltCallback = pCallback; + break; + case HAL_QSPI_TX_CPLT_CB_ID : + hqspi->TxCpltCallback = pCallback; + break; + case HAL_QSPI_RX_HALF_CPLT_CB_ID : + hqspi->RxHalfCpltCallback = pCallback; + break; + case HAL_QSPI_TX_HALF_CPLT_CB_ID : + hqspi->TxHalfCpltCallback = pCallback; + break; + case HAL_QSPI_STATUS_MATCH_CB_ID : + hqspi->StatusMatchCallback = pCallback; + break; + case HAL_QSPI_TIMEOUT_CB_ID : + hqspi->TimeOutCallback = pCallback; + break; + case HAL_QSPI_MSP_INIT_CB_ID : + hqspi->MspInitCallback = pCallback; + break; + case HAL_QSPI_MSP_DEINIT_CB_ID : + hqspi->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hqspi->State == HAL_QSPI_STATE_RESET) + { + switch (CallbackId) + { + case HAL_QSPI_MSP_INIT_CB_ID : + hqspi->MspInitCallback = pCallback; + break; + case HAL_QSPI_MSP_DEINIT_CB_ID : + hqspi->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hqspi); + return status; +} + +/** + * @brief Unregister a User QSPI Callback + * QSPI Callback is redirected to the weak (surcharged) predefined callback + * @param hqspi QSPI handle + * @param CallbackId ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_QSPI_ERROR_CB_ID QSPI Error Callback ID + * @arg @ref HAL_QSPI_ABORT_CB_ID QSPI Abort Callback ID + * @arg @ref HAL_QSPI_FIFO_THRESHOLD_CB_ID QSPI FIFO Threshold Callback ID + * @arg @ref HAL_QSPI_CMD_CPLT_CB_ID QSPI Command Complete Callback ID + * @arg @ref HAL_QSPI_RX_CPLT_CB_ID QSPI Rx Complete Callback ID + * @arg @ref HAL_QSPI_TX_CPLT_CB_ID QSPI Tx Complete Callback ID + * @arg @ref HAL_QSPI_RX_HALF_CPLT_CB_ID QSPI Rx Half Complete Callback ID + * @arg @ref HAL_QSPI_TX_HALF_CPLT_CB_ID QSPI Tx Half Complete Callback ID + * @arg @ref HAL_QSPI_STATUS_MATCH_CB_ID QSPI Status Match Callback ID + * @arg @ref HAL_QSPI_TIMEOUT_CB_ID QSPI Timeout Callback ID + * @arg @ref HAL_QSPI_MSP_INIT_CB_ID QSPI MspInit callback ID + * @arg @ref HAL_QSPI_MSP_DEINIT_CB_ID QSPI MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_QSPI_UnRegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + switch (CallbackId) + { + case HAL_QSPI_ERROR_CB_ID : + hqspi->ErrorCallback = HAL_QSPI_ErrorCallback; + break; + case HAL_QSPI_ABORT_CB_ID : + hqspi->AbortCpltCallback = HAL_QSPI_AbortCpltCallback; + break; + case HAL_QSPI_FIFO_THRESHOLD_CB_ID : + hqspi->FifoThresholdCallback = HAL_QSPI_FifoThresholdCallback; + break; + case HAL_QSPI_CMD_CPLT_CB_ID : + hqspi->CmdCpltCallback = HAL_QSPI_CmdCpltCallback; + break; + case HAL_QSPI_RX_CPLT_CB_ID : + hqspi->RxCpltCallback = HAL_QSPI_RxCpltCallback; + break; + case HAL_QSPI_TX_CPLT_CB_ID : + hqspi->TxCpltCallback = HAL_QSPI_TxCpltCallback; + break; + case HAL_QSPI_RX_HALF_CPLT_CB_ID : + hqspi->RxHalfCpltCallback = HAL_QSPI_RxHalfCpltCallback; + break; + case HAL_QSPI_TX_HALF_CPLT_CB_ID : + hqspi->TxHalfCpltCallback = HAL_QSPI_TxHalfCpltCallback; + break; + case HAL_QSPI_STATUS_MATCH_CB_ID : + hqspi->StatusMatchCallback = HAL_QSPI_StatusMatchCallback; + break; + case HAL_QSPI_TIMEOUT_CB_ID : + hqspi->TimeOutCallback = HAL_QSPI_TimeOutCallback; + break; + case HAL_QSPI_MSP_INIT_CB_ID : + hqspi->MspInitCallback = HAL_QSPI_MspInit; + break; + case HAL_QSPI_MSP_DEINIT_CB_ID : + hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit; + break; + default : + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hqspi->State == HAL_QSPI_STATE_RESET) + { + switch (CallbackId) + { + case HAL_QSPI_MSP_INIT_CB_ID : + hqspi->MspInitCallback = HAL_QSPI_MspInit; + break; + case HAL_QSPI_MSP_DEINIT_CB_ID : + hqspi->MspDeInitCallback = HAL_QSPI_MspDeInit; + break; + default : + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hqspi->ErrorCode |= HAL_QSPI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hqspi); + return status; +} +#endif + +/** + * @} + */ + +/** @defgroup QSPI_Exported_Functions_Group3 Peripheral Control and State functions + * @brief QSPI control and State functions + * +@verbatim + =============================================================================== + ##### Peripheral Control and State functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to : + (+) Check in run-time the state of the driver. + (+) Check the error code set during last operation. + (+) Abort any operation. + + +@endverbatim + * @{ + */ + +/** + * @brief Return the QSPI handle state. + * @param hqspi QSPI handle + * @retval HAL state + */ +HAL_QSPI_StateTypeDef HAL_QSPI_GetState(QSPI_HandleTypeDef *hqspi) +{ + /* Return QSPI handle state */ + return hqspi->State; +} + +/** +* @brief Return the QSPI error code. +* @param hqspi QSPI handle +* @retval QSPI Error Code +*/ +uint32_t HAL_QSPI_GetError(QSPI_HandleTypeDef *hqspi) +{ + return hqspi->ErrorCode; +} + +/** +* @brief Abort the current transmission. +* @param hqspi QSPI handle +* @retval HAL status +*/ +HAL_StatusTypeDef HAL_QSPI_Abort(QSPI_HandleTypeDef *hqspi) +{ + HAL_StatusTypeDef status = HAL_OK; + uint32_t tickstart = HAL_GetTick(); + + /* Check if the state is in one of the busy states */ + if (((uint32_t)hqspi->State & 0x2U) != 0U) + { + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Abort DMA channel */ + status = HAL_DMA_Abort(hqspi->hdma); + if(status != HAL_OK) + { + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + } + } + + if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) != RESET) + { + /* Configure QSPI: CR register with Abort request */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); + + /* Wait until TC flag is set to go back in idle state */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_TC, SET, tickstart, hqspi->Timeout); + + if (status == HAL_OK) + { + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Wait until BUSY flag is reset */ + status = QSPI_WaitFlagStateUntilTimeout(hqspi, QSPI_FLAG_BUSY, RESET, tickstart, hqspi->Timeout); + } + + if (status == HAL_OK) + { + /* Reset functional mode configuration to indirect write mode by default */ + CLEAR_BIT(hqspi->Instance->CCR, QUADSPI_CCR_FMODE); + + /* Update state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + else + { + /* Update state */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + + return status; +} + +/** +* @brief Abort the current transmission (non-blocking function) +* @param hqspi QSPI handle +* @retval HAL status +*/ +HAL_StatusTypeDef HAL_QSPI_Abort_IT(QSPI_HandleTypeDef *hqspi) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check if the state is in one of the busy states */ + if (((uint32_t)hqspi->State & 0x2U) != 0U) + { + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Update QSPI state */ + hqspi->State = HAL_QSPI_STATE_ABORT; + + /* Disable all interrupts */ + __HAL_QSPI_DISABLE_IT(hqspi, (QSPI_IT_TO | QSPI_IT_SM | QSPI_IT_FT | QSPI_IT_TC | QSPI_IT_TE)); + + if ((hqspi->Instance->CR & QUADSPI_CR_DMAEN) != 0U) + { + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Abort DMA channel */ + hqspi->hdma->XferAbortCallback = QSPI_DMAAbortCplt; + if (HAL_DMA_Abort_IT(hqspi->hdma) != HAL_OK) + { + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Abort Complete callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->AbortCpltCallback(hqspi); +#else + HAL_QSPI_AbortCpltCallback(hqspi); +#endif + } + } + else + { + if (__HAL_QSPI_GET_FLAG(hqspi, QSPI_FLAG_BUSY) != RESET) + { + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Enable the QSPI Transfer Complete Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); + + /* Configure QSPI: CR register with Abort request */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); + } + else + { + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + } + } + } + return status; +} + +/** @brief Set QSPI timeout. + * @param hqspi QSPI handle. + * @param Timeout Timeout for the QSPI memory access. + * @retval None + */ +void HAL_QSPI_SetTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Timeout) +{ + hqspi->Timeout = Timeout; +} + +/** @brief Set QSPI Fifo threshold. + * @param hqspi QSPI handle. + * @param Threshold Threshold of the Fifo (value between 1 and 16). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_SetFifoThreshold(QSPI_HandleTypeDef *hqspi, uint32_t Threshold) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + /* Synchronize init structure with new FIFO threshold value */ + hqspi->Init.FifoThreshold = Threshold; + + /* Configure QSPI FIFO Threshold */ + MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FTHRES, + ((hqspi->Init.FifoThreshold - 1U) << QUADSPI_CR_FTHRES_Pos)); + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** @brief Get QSPI Fifo threshold. + * @param hqspi QSPI handle. + * @retval Fifo threshold (value between 1 and 16) + */ +uint32_t HAL_QSPI_GetFifoThreshold(QSPI_HandleTypeDef *hqspi) +{ + return ((READ_BIT(hqspi->Instance->CR, QUADSPI_CR_FTHRES) >> QUADSPI_CR_FTHRES_Pos) + 1U); +} + +/** @brief Set FlashID. + * @param hqspi QSPI handle. + * @param FlashID Index of the flash memory to be accessed. + * This parameter can be a value of @ref QSPI_Flash_Select. + * @note The FlashID is ignored when dual flash mode is enabled. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_QSPI_SetFlashID(QSPI_HandleTypeDef *hqspi, uint32_t FlashID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameter */ + assert_param(IS_QSPI_FLASH_ID(FlashID)); + + /* Process locked */ + __HAL_LOCK(hqspi); + + if(hqspi->State == HAL_QSPI_STATE_READY) + { + /* Synchronize init structure with new FlashID value */ + hqspi->Init.FlashID = FlashID; + + /* Configure QSPI FlashID */ + MODIFY_REG(hqspi->Instance->CR, QUADSPI_CR_FSEL, FlashID); + } + else + { + status = HAL_BUSY; + } + + /* Process unlocked */ + __HAL_UNLOCK(hqspi); + + /* Return function status */ + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup QSPI_Private_Functions QSPI Private Functions + * @{ + */ + +/** + * @brief DMA QSPI receive process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMARxCplt(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hdma->Parent); + hqspi->RxXferCount = 0U; + + /* Enable the QSPI transfer complete Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); +} + +/** + * @brief DMA QSPI transmit process complete callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMATxCplt(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hdma->Parent); + hqspi->TxXferCount = 0U; + + /* Enable the QSPI transfer complete Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); +} + +/** + * @brief DMA QSPI receive process half complete callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hdma->Parent); + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->RxHalfCpltCallback(hqspi); +#else + HAL_QSPI_RxHalfCpltCallback(hqspi); +#endif +} + +/** + * @brief DMA QSPI transmit process half complete callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = (QSPI_HandleTypeDef*)(hdma->Parent); + +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->TxHalfCpltCallback(hqspi); +#else + HAL_QSPI_TxHalfCpltCallback(hqspi); +#endif +} + +/** + * @brief DMA QSPI communication error callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMAError(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )(hdma->Parent); + + /* if DMA error is FIFO error ignore it */ + if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) + { + hqspi->RxXferCount = 0U; + hqspi->TxXferCount = 0U; + hqspi->ErrorCode |= HAL_QSPI_ERROR_DMA; + + /* Disable the DMA transfer by clearing the DMAEN bit in the QSPI CR register */ + CLEAR_BIT(hqspi->Instance->CR, QUADSPI_CR_DMAEN); + + /* Abort the QSPI */ + (void)HAL_QSPI_Abort_IT(hqspi); + + } +} + +/** + * @brief DMA QSPI abort complete callback. + * @param hdma DMA handle + * @retval None + */ +static void QSPI_DMAAbortCplt(DMA_HandleTypeDef *hdma) +{ + QSPI_HandleTypeDef* hqspi = ( QSPI_HandleTypeDef* )(hdma->Parent); + + hqspi->RxXferCount = 0U; + hqspi->TxXferCount = 0U; + + if(hqspi->State == HAL_QSPI_STATE_ABORT) + { + /* DMA Abort called by QSPI abort */ + /* Clear interrupt */ + __HAL_QSPI_CLEAR_FLAG(hqspi, QSPI_FLAG_TC); + + /* Enable the QSPI Transfer Complete Interrupt */ + __HAL_QSPI_ENABLE_IT(hqspi, QSPI_IT_TC); + + /* Configure QSPI: CR register with Abort request */ + SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT); + } + else + { + /* DMA Abort called due to a transfer error interrupt */ + /* Change state of QSPI */ + hqspi->State = HAL_QSPI_STATE_READY; + + /* Error callback */ +#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1) + hqspi->ErrorCallback(hqspi); +#else + HAL_QSPI_ErrorCallback(hqspi); +#endif + } +} + +/** + * @brief Wait for a flag state until timeout. + * @param hqspi QSPI handle + * @param Flag Flag checked + * @param State Value of the flag expected + * @param Tickstart Tick start value + * @param Timeout Duration of the timeout + * @retval HAL status + */ +static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout(QSPI_HandleTypeDef *hqspi, uint32_t Flag, + FlagStatus State, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is in expected state */ + while((__HAL_QSPI_GET_FLAG(hqspi, Flag)) != State) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if(((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U)) + { + hqspi->State = HAL_QSPI_STATE_ERROR; + hqspi->ErrorCode |= HAL_QSPI_ERROR_TIMEOUT; + + return HAL_ERROR; + } + } + } + return HAL_OK; +} + +/** + * @brief Wait for a flag state until timeout using CPU cycle. + * @param hqspi : QSPI handle + * @param Flag : Flag checked + * @param State : Value of the flag expected + * @param Timeout : Duration of the timeout + * @retval HAL status + */ +static HAL_StatusTypeDef QSPI_WaitFlagStateUntilTimeout_CPUCycle(QSPI_HandleTypeDef *hqspi, uint32_t Flag, FlagStatus State, uint32_t Timeout) +{ + __IO uint32_t count = Timeout * (SystemCoreClock / 16U / 1000U); + do + { + if (count-- == 0U) + { + hqspi->State = HAL_QSPI_STATE_ERROR; + hqspi->ErrorCode |= HAL_QSPI_ERROR_TIMEOUT; + return HAL_TIMEOUT; + } + } + while ((__HAL_QSPI_GET_FLAG(hqspi, Flag)) != State); + + return HAL_OK; +} + +/** + * @brief Configure the communication registers. + * @param hqspi QSPI handle + * @param cmd structure that contains the command configuration information + * @param FunctionalMode functional mode to configured + * This parameter can be one of the following values: + * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_WRITE: Indirect write mode + * @arg QSPI_FUNCTIONAL_MODE_INDIRECT_READ: Indirect read mode + * @arg QSPI_FUNCTIONAL_MODE_AUTO_POLLING: Automatic polling mode + * @arg QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED: Memory-mapped mode + * @retval None + */ +static void QSPI_Config(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t FunctionalMode) +{ + assert_param(IS_QSPI_FUNCTIONAL_MODE(FunctionalMode)); + + if ((cmd->DataMode != QSPI_DATA_NONE) && (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED)) + { + /* Configure QSPI: DLR register with the number of data to read or write */ + WRITE_REG(hqspi->Instance->DLR, (cmd->NbData - 1U)); + } + + if (cmd->InstructionMode != QSPI_INSTRUCTION_NONE) + { + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + /* Configure QSPI: ABR register with alternate bytes value */ + WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes); + + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + /*---- Command with instruction, address and alternate bytes ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateBytesSize | cmd->AlternateByteMode | + cmd->AddressSize | cmd->AddressMode | cmd->InstructionMode | + cmd->Instruction | FunctionalMode)); + + if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) + { + /* Configure QSPI: AR register with address value */ + WRITE_REG(hqspi->Instance->AR, cmd->Address); + } + } + else + { + /*---- Command with instruction and alternate bytes ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateBytesSize | cmd->AlternateByteMode | + cmd->AddressMode | cmd->InstructionMode | + cmd->Instruction | FunctionalMode)); + } + } + else + { + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + /*---- Command with instruction and address ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateByteMode | cmd->AddressSize | cmd->AddressMode | + cmd->InstructionMode | cmd->Instruction | FunctionalMode)); + + if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) + { + /* Configure QSPI: AR register with address value */ + WRITE_REG(hqspi->Instance->AR, cmd->Address); + } + } + else + { + /*---- Command with only instruction ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateByteMode | cmd->AddressMode | + cmd->InstructionMode | cmd->Instruction | FunctionalMode)); + } + } + } + else + { + if (cmd->AlternateByteMode != QSPI_ALTERNATE_BYTES_NONE) + { + /* Configure QSPI: ABR register with alternate bytes value */ + WRITE_REG(hqspi->Instance->ABR, cmd->AlternateBytes); + + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + /*---- Command with address and alternate bytes ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateBytesSize | cmd->AlternateByteMode | + cmd->AddressSize | cmd->AddressMode | + cmd->InstructionMode | FunctionalMode)); + + if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) + { + /* Configure QSPI: AR register with address value */ + WRITE_REG(hqspi->Instance->AR, cmd->Address); + } + } + else + { + /*---- Command with only alternate bytes ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateBytesSize | cmd->AlternateByteMode | + cmd->AddressMode | cmd->InstructionMode | FunctionalMode)); + } + } + else + { + if (cmd->AddressMode != QSPI_ADDRESS_NONE) + { + /*---- Command with only address ----*/ + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateByteMode | cmd->AddressSize | + cmd->AddressMode | cmd->InstructionMode | FunctionalMode)); + + if (FunctionalMode != QSPI_FUNCTIONAL_MODE_MEMORY_MAPPED) + { + /* Configure QSPI: AR register with address value */ + WRITE_REG(hqspi->Instance->AR, cmd->Address); + } + } + else + { + /*---- Command with only data phase ----*/ + if (cmd->DataMode != QSPI_DATA_NONE) + { + /* Configure QSPI: CCR register with all communications parameters */ + WRITE_REG(hqspi->Instance->CCR, (cmd->DdrMode | cmd->DdrHoldHalfCycle | cmd->SIOOMode | + cmd->DataMode | (cmd->DummyCycles << QUADSPI_CCR_DCYC_Pos) | + cmd->AlternateByteMode | cmd->AddressMode | + cmd->InstructionMode | FunctionalMode)); + } + } + } + } +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_QSPI_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(QUADSPI) */ diff --git a/libs/hal/stm32f4xx_hal_rcc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c similarity index 99% rename from libs/hal/stm32f4xx_hal_rcc.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c index f187348..8e494e6 100644 --- a/libs/hal/stm32f4xx_hal_rcc.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc.c @@ -479,7 +479,7 @@ __weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc /* Get Start Tick */ tickstart = HAL_GetTick(); - /* Wait till PLL is ready */ + /* Wait till PLL is disabled */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE) @@ -517,7 +517,7 @@ __weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc /* Get Start Tick */ tickstart = HAL_GetTick(); - /* Wait till PLL is ready */ + /* Wait till PLL is disabled */ while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET) { if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE) diff --git a/libs/hal/stm32f4xx_hal_rcc_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c similarity index 100% rename from libs/hal/stm32f4xx_hal_rcc_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rcc_ex.c diff --git a/libs/hal/stm32f4xx_hal_rng.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c similarity index 100% rename from libs/hal/stm32f4xx_hal_rng.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rng.c diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c new file mode 100644 index 0000000..f4d5dbc --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc.c @@ -0,0 +1,1908 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_rtc.c + * @author MCD Application Team + * @brief RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real-Time Clock (RTC) peripheral: + * + Initialization and de-initialization functions + * + RTC Calendar (Time and Date) configuration functions + * + RTC Alarms (Alarm A and Alarm B) configuration functions + * + Peripheral Control functions + * + Peripheral State functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 + ============================================================================== + ##### RTC and Backup Domain Operating Condition ##### + ============================================================================== + [..] The real-time clock (RTC), the RTC backup registers, and the backup + SRAM (BKP SRAM) can be powered from the VBAT voltage when the main + VDD supply is powered off. + To retain the content of the RTC backup registers, BKP SRAM, and supply + the RTC when VDD is turned off, VBAT pin can be connected to an optional + standby voltage supplied by a battery or by another source. + + [..] To allow the RTC operating even when the main digital supply (VDD) is turned + off, the VBAT pin powers the following blocks: + (#) The RTC + (#) The LSE oscillator + (#) The BKP SRAM when the low power backup regulator is enabled + (#) PC13 to PC15 I/Os, plus PI8 I/O (when available) + + [..] When the backup domain is supplied by VDD (analog switch connected to VDD), + the following pins are available: + (#) PC14 and PC15 can be used as either GPIO or LSE pins + (#) PC13 can be used as a GPIO or as the RTC_AF1 pin + (#) PI8 can be used as a GPIO or as the RTC_AF2 pin + + [..] When the backup domain is supplied by VBAT (analog switch connected to VBAT + because VDD is not present), the following pins are available: + (#) PC14 and PC15 can be used as LSE pins only + (#) PC13 can be used as the RTC_AF1 pin + (#) PI8 can be used as the RTC_AF2 pin + + ##### Backup Domain Reset ##### + ================================================================== + [..] The backup domain reset sets all RTC registers and the RCC_BDCR register + to their reset values. + The BKP SRAM is not affected by this reset. The only way to reset the BKP + SRAM is through the Flash interface by requesting a protection level + change from 1 to 0. + [..] A backup domain reset is generated when one of the following events occurs: + (#) Software reset, triggered by setting the BDRST bit in the + RCC Backup domain control register (RCC_BDCR). + (#) VDD or VBAT power on, if both supplies have previously been powered off. + + ##### Backup Domain Access ##### + ================================================================== + [..] After reset, the backup domain (RTC registers, RTC backup data registers + and BKP SRAM) is protected against possible unwanted write accesses. + [..] To enable access to the RTC Domain and RTC registers, proceed as follows: + (+) Enable the Power Controller (PWR) APB1 interface clock using the + __HAL_RCC_PWR_CLK_ENABLE() macro. + (+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function. + (+) Select the RTC clock source using the __HAL_RCC_RTC_CONFIG() macro. + (+) Enable RTC Clock using the __HAL_RCC_RTC_ENABLE() macro. + + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + (+) Enable the RTC domain access (see description in the section above). + (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** Time and Date configuration *** + =================================== + [..] + (+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime() + and HAL_RTC_SetDate() functions. + (+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() + functions. + (+) To manage the RTC summer or winter time change, use the following + functions: + (++) HAL_RTC_DST_Add1Hour() or HAL_RTC_DST_Sub1Hour to add or subtract + 1 hour from the calendar time. + (++) HAL_RTC_DST_SetStoreOperation() or HAL_RTC_DST_ClearStoreOperation + to memorize whether the time change has been performed or not. + + *** Alarm configuration *** + =========================== + [..] + (+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function. + You can also configure the RTC Alarm with interrupt mode using the + HAL_RTC_SetAlarm_IT() function. + (+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function. + + ##### RTC and low power modes ##### + ================================================================== + [..] The MCU can be woken up from a low power mode by an RTC alternate + function. + [..] The RTC alternate functions are the RTC alarms (Alarm A and Alarm B), + RTC wakeup, RTC tamper event detection and RTC timestamp event detection. + These RTC alternate functions can wake up the system from the Stop and + Standby low power modes. + [..] The system can also wake up from low power modes without depending + on an external interrupt (Auto-wakeup mode), by using the RTC alarm + or the RTC wakeup events. + [..] The RTC provides a programmable time base for waking up from the + Stop or Standby mode at regular intervals. + Wakeup from STOP and STANDBY modes is possible only when the RTC clock + source is LSE or LSI. + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_RTC_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_RTC_RegisterCallback() to register an interrupt callback. + [..] + Function HAL_RTC_RegisterCallback() allows to register following callbacks: + (+) AlarmAEventCallback : RTC Alarm A Event callback. + (+) AlarmBEventCallback : RTC Alarm B Event callback. + (+) TimeStampEventCallback : RTC Timestamp Event callback. + (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback. + (+) Tamper1EventCallback : RTC Tamper 1 Event callback. + (+) Tamper2EventCallback : RTC Tamper 2 Event callback. + (+) MspInitCallback : RTC MspInit callback. + (+) MspDeInitCallback : RTC MspDeInit callback. + [..] + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + Use function HAL_RTC_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) AlarmAEventCallback : RTC Alarm A Event callback. + (+) AlarmBEventCallback : RTC Alarm B Event callback. + (+) TimeStampEventCallback : RTC Timestamp Event callback. + (+) WakeUpTimerEventCallback : RTC WakeUpTimer Event callback. + (+) Tamper1EventCallback : RTC Tamper 1 Event callback. + (+) Tamper2EventCallback : RTC Tamper 2 Event callback. + (+) MspInitCallback : RTC MspInit callback. + (+) MspDeInitCallback : RTC MspDeInit callback. + [..] + By default, after the HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET, + all callbacks are set to the corresponding weak functions: + examples AlarmAEventCallback(), WakeUpTimerEventCallback(). + Exception done for MspInit() and MspDeInit() callbacks that are reset to the + legacy weak function in the HAL_RTC_Init()/HAL_RTC_DeInit() only + when these callbacks are null (not registered beforehand). + If not, MspInit() or MspDeInit() are not null, HAL_RTC_Init()/HAL_RTC_DeInit() + keep and use the user MspInit()/MspDeInit() callbacks (registered beforehand). + [..] + Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only. + Exception done MspInit()/MspDeInit() that can be registered/unregistered + in HAL_RTC_STATE_READY or HAL_RTC_STATE_RESET state. + Thus registered (user) MspInit()/MspDeInit() callbacks can be used during the + Init/DeInit. + In that case first register the MspInit()/MspDeInit() user callbacks + using HAL_RTC_RegisterCallback() before calling HAL_RTC_DeInit() + or HAL_RTC_Init() functions. + [..] + When The compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all + callbacks are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTC RTC + * @brief RTC HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTC_Exported_Functions RTC Exported Functions + * @{ + */ + +/** @defgroup RTC_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to initialize and configure the + RTC Prescaler (Synchronous and Asynchronous), RTC Hour format, disable + RTC registers Write protection, enter and exit the RTC initialization mode, + RTC registers synchronization check and reference clock detection enable. + (#) The RTC Prescaler is programmed to generate the RTC 1Hz time base. + It is split into 2 programmable prescalers to minimize power consumption. + (++) A 7-bit asynchronous prescaler and a 15-bit synchronous prescaler. + (++) When both prescalers are used, it is recommended to configure the + asynchronous prescaler to a high value to minimize power consumption. + (#) All RTC registers are Write protected. Writing to the RTC registers + is enabled by writing a key into the Write Protection register, RTC_WPR. + (#) To configure the RTC Calendar, user application should enter + initialization mode. In this mode, the calendar counter is stopped + and its value can be updated. When the initialization sequence is + complete, the calendar restarts counting after 4 RTCCLK cycles. + (#) To read the calendar through the shadow registers after Calendar + initialization, calendar update or after wakeup from low power modes + the software must first clear the RSF flag. The software must then + wait until it is set again before reading the calendar, which means + that the calendar registers have been correctly copied into the + RTC_TR and RTC_DR shadow registers. The HAL_RTC_WaitForSynchro() function + implements the above software sequence (RSF clear and RSF check). + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the RTC peripheral + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status = HAL_ERROR; + + /* Check RTC handler validity */ + if (hrtc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + assert_param(IS_RTC_HOUR_FORMAT(hrtc->Init.HourFormat)); + assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv)); + assert_param(IS_RTC_SYNCH_PREDIV(hrtc->Init.SynchPrediv)); + assert_param(IS_RTC_OUTPUT(hrtc->Init.OutPut)); + assert_param(IS_RTC_OUTPUT_POL(hrtc->Init.OutPutPolarity)); + assert_param(IS_RTC_OUTPUT_TYPE(hrtc->Init.OutPutType)); + +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + if (hrtc->State == HAL_RTC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrtc->Lock = HAL_UNLOCKED; + + hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */ + hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */ + hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */ + hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */ + hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */ +#if defined(RTC_TAMPER2_SUPPORT) + hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */ +#endif /* RTC_TAMPER2_SUPPORT */ + + if (hrtc->MspInitCallback == NULL) + { + hrtc->MspInitCallback = HAL_RTC_MspInit; + } + /* Init the low level hardware */ + hrtc->MspInitCallback(hrtc); + + if (hrtc->MspDeInitCallback == NULL) + { + hrtc->MspDeInitCallback = HAL_RTC_MspDeInit; + } + } +#else /* USE_HAL_RTC_REGISTER_CALLBACKS */ + if (hrtc->State == HAL_RTC_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hrtc->Lock = HAL_UNLOCKED; + + /* Initialize RTC MSP */ + HAL_RTC_MspInit(hrtc); + } +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Check whether the calendar needs to be initialized */ + if (__HAL_RTC_IS_CALENDAR_INITIALIZED(hrtc) == 0U) + { + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Clear RTC_CR FMT, OSEL and POL Bits */ + hrtc->Instance->CR &= ((uint32_t)~(RTC_CR_FMT | RTC_CR_OSEL | RTC_CR_POL)); + /* Set RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)(hrtc->Init.HourFormat | hrtc->Init.OutPut | hrtc->Init.OutPutPolarity); + + /* Configure the RTC PRER */ + hrtc->Instance->PRER = (uint32_t)(hrtc->Init.SynchPrediv); + hrtc->Instance->PRER |= (uint32_t)(hrtc->Init.AsynchPrediv << RTC_PRER_PREDIV_A_Pos); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->Instance->TAFCR &= (uint32_t)~RTC_OUTPUT_TYPE_PUSHPULL; + hrtc->Instance->TAFCR |= (uint32_t)(hrtc->Init.OutPutType); + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + } + else + { + /* The calendar is already initialized */ + status = HAL_OK; + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + return status; +} + +/** + * @brief DeInitializes the RTC peripheral + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @note This function does not reset the RTC Backup Data registers. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status = HAL_ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance)); + + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Reset RTC registers */ + hrtc->Instance->TR = 0x00000000U; + hrtc->Instance->DR = (RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0); + hrtc->Instance->CR &= 0x00000000U; + hrtc->Instance->WUTR = RTC_WUTR_WUT; + hrtc->Instance->PRER = (uint32_t)(RTC_PRER_PREDIV_A | 0x000000FFU); + hrtc->Instance->CALIBR = 0x00000000U; + hrtc->Instance->ALRMAR = 0x00000000U; + hrtc->Instance->ALRMBR = 0x00000000U; + hrtc->Instance->CALR = 0x00000000U; + hrtc->Instance->SHIFTR = 0x00000000U; + hrtc->Instance->ALRMASSR = 0x00000000U; + hrtc->Instance->ALRMBSSR = 0x00000000U; + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + if (status == HAL_OK) + { + /* Reset Tamper and alternate functions configuration register */ + hrtc->Instance->TAFCR = 0x00000000U; + +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + if (hrtc->MspDeInitCallback == NULL) + { + hrtc->MspDeInitCallback = HAL_RTC_MspDeInit; + } + + /* DeInit the low level hardware: CLOCK, NVIC.*/ + hrtc->MspDeInitCallback(hrtc); +#else /* USE_HAL_RTC_REGISTER_CALLBACKS */ + /* De-Initialize RTC MSP */ + HAL_RTC_MspDeInit(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + hrtc->State = HAL_RTC_STATE_RESET; + } + + /* Release Lock */ + __HAL_UNLOCK(hrtc); + + return status; +} + +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) +/** + * @brief Registers a User RTC Callback + * To be used instead of the weak predefined callback + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID + * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID + * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID Timestamp Event Callback ID + * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID Wakeup Timer Event Callback ID + * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID + * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Callback ID + * @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID + * @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID + * @note HAL_RTC_TAMPER2_EVENT_CB_ID is not applicable to all devices. + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hrtc); + + if (HAL_RTC_STATE_READY == hrtc->State) + { + switch (CallbackID) + { + case HAL_RTC_ALARM_A_EVENT_CB_ID : + hrtc->AlarmAEventCallback = pCallback; + break; + + case HAL_RTC_ALARM_B_EVENT_CB_ID : + hrtc->AlarmBEventCallback = pCallback; + break; + + case HAL_RTC_TIMESTAMP_EVENT_CB_ID : + hrtc->TimeStampEventCallback = pCallback; + break; + + case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID : + hrtc->WakeUpTimerEventCallback = pCallback; + break; + + case HAL_RTC_TAMPER1_EVENT_CB_ID : + hrtc->Tamper1EventCallback = pCallback; + break; + +#if defined(RTC_TAMPER2_SUPPORT) + case HAL_RTC_TAMPER2_EVENT_CB_ID : + hrtc->Tamper2EventCallback = pCallback; + break; +#endif /* RTC_TAMPER2_SUPPORT */ + + case HAL_RTC_MSPINIT_CB_ID : + hrtc->MspInitCallback = pCallback; + break; + + case HAL_RTC_MSPDEINIT_CB_ID : + hrtc->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_RTC_STATE_RESET == hrtc->State) + { + switch (CallbackID) + { + case HAL_RTC_MSPINIT_CB_ID : + hrtc->MspInitCallback = pCallback; + break; + + case HAL_RTC_MSPDEINIT_CB_ID : + hrtc->MspDeInitCallback = pCallback; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Unregisters an RTC Callback + * RTC callabck is redirected to the weak predefined callback + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID + * @arg @ref HAL_RTC_ALARM_B_EVENT_CB_ID Alarm B Event Callback ID + * @arg @ref HAL_RTC_TIMESTAMP_EVENT_CB_ID Timestamp Event Callback ID + * @arg @ref HAL_RTC_WAKEUPTIMER_EVENT_CB_ID Wakeup Timer Event Callback ID + * @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID + * @arg @ref HAL_RTC_TAMPER2_EVENT_CB_ID Tamper 2 Callback ID + * @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID + * @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID + * @note HAL_RTC_TAMPER2_EVENT_CB_ID is not applicable to all devices. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hrtc); + + if (HAL_RTC_STATE_READY == hrtc->State) + { + switch (CallbackID) + { + case HAL_RTC_ALARM_A_EVENT_CB_ID : + hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */ + break; + + case HAL_RTC_ALARM_B_EVENT_CB_ID : + hrtc->AlarmBEventCallback = HAL_RTCEx_AlarmBEventCallback; /* Legacy weak AlarmBEventCallback */ + break; + + case HAL_RTC_TIMESTAMP_EVENT_CB_ID : + hrtc->TimeStampEventCallback = HAL_RTCEx_TimeStampEventCallback; /* Legacy weak TimeStampEventCallback */ + break; + + case HAL_RTC_WAKEUPTIMER_EVENT_CB_ID : + hrtc->WakeUpTimerEventCallback = HAL_RTCEx_WakeUpTimerEventCallback; /* Legacy weak WakeUpTimerEventCallback */ + break; + + case HAL_RTC_TAMPER1_EVENT_CB_ID : + hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */ + break; + +#if defined(RTC_TAMPER2_SUPPORT) + case HAL_RTC_TAMPER2_EVENT_CB_ID : + hrtc->Tamper2EventCallback = HAL_RTCEx_Tamper2EventCallback; /* Legacy weak Tamper2EventCallback */ + break; +#endif /* RTC_TAMPER2_SUPPORT */ + + case HAL_RTC_MSPINIT_CB_ID : + hrtc->MspInitCallback = HAL_RTC_MspInit; + break; + + case HAL_RTC_MSPDEINIT_CB_ID : + hrtc->MspDeInitCallback = HAL_RTC_MspDeInit; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_RTC_STATE_RESET == hrtc->State) + { + switch (CallbackID) + { + case HAL_RTC_MSPINIT_CB_ID : + hrtc->MspInitCallback = HAL_RTC_MspInit; + break; + + case HAL_RTC_MSPDEINIT_CB_ID : + hrtc->MspDeInitCallback = HAL_RTC_MspDeInit; + break; + + default : + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hrtc); + + return status; +} +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + +/** + * @brief Initializes the RTC MSP. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTC_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes the RTC MSP. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTC_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group2 RTC Time and Date functions + * @brief RTC Time and Date functions + * +@verbatim + =============================================================================== + ##### RTC Time and Date functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Time and Date features + +@endverbatim + * @{ + */ + +/** + * @brief Sets RTC current time. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sTime Pointer to Time structure + * @note DayLightSaving and StoreOperation interfaces are deprecated. + * To manage Daylight Saving Time, please use HAL_RTC_DST_xxx functions. + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0U; + HAL_StatusTypeDef status; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_DAYLIGHT_SAVING(sTime->DayLightSaving)); + assert_param(IS_RTC_STORE_OPERATION(sTime->StoreOperation)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if (Format == RTC_FORMAT_BIN) + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(sTime->Hours)); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(sTime->Hours)); + } + assert_param(IS_RTC_MINUTES(sTime->Minutes)); + assert_param(IS_RTC_SECONDS(sTime->Seconds)); + + tmpreg = (uint32_t)(( (uint32_t)RTC_ByteToBcd2(sTime->Hours) << RTC_TR_HU_Pos) | \ + ( (uint32_t)RTC_ByteToBcd2(sTime->Minutes) << RTC_TR_MNU_Pos) | \ + ( (uint32_t)RTC_ByteToBcd2(sTime->Seconds)) | \ + (((uint32_t)sTime->TimeFormat) << RTC_TR_PM_Pos)); + } + else + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sTime->Hours))); + assert_param(IS_RTC_HOURFORMAT12(sTime->TimeFormat)); + } + else + { + sTime->TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours))); + } + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds))); + tmpreg = (((uint32_t)(sTime->Hours) << RTC_TR_HU_Pos) | \ + ((uint32_t)(sTime->Minutes) << RTC_TR_MNU_Pos) | \ + ((uint32_t) sTime->Seconds) | \ + ((uint32_t)(sTime->TimeFormat) << RTC_TR_PM_Pos)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Set the RTC_TR register */ + hrtc->Instance->TR = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK); + + /* Clear the bits to be configured (Deprecated. Use HAL_RTC_DST_xxx functions instead) */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_BKP; + + /* Configure the RTC_CR register (Deprecated. Use HAL_RTC_DST_xxx functions instead) */ + hrtc->Instance->CR |= (uint32_t)(sTime->DayLightSaving | sTime->StoreOperation); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Gets RTC current time. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sTime Pointer to Time structure + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You can use SubSeconds and SecondFraction (sTime structure fields + * returned) to convert SubSeconds value in second fraction ratio with + * time unit following generic formula: + * Second fraction ratio * time_unit = + * [(SecondFraction - SubSeconds) / (SecondFraction + 1)] * time_unit + * This conversion can be performed only if no shift operation is pending + * (ie. SHFP=0) when PREDIV_S >= SS + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the + * values in the higher-order calendar shadow registers to ensure + * consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers + * until current date is read to ensure consistency between the time and + * date values. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get subseconds value from the corresponding register */ + sTime->SubSeconds = (uint32_t)(hrtc->Instance->SSR); + + /* Get SecondFraction structure field from the corresponding register field*/ + sTime->SecondFraction = (uint32_t)(hrtc->Instance->PRER & RTC_PRER_PREDIV_S); + + /* Get the TR register */ + tmpreg = (uint32_t)(hrtc->Instance->TR & RTC_TR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> RTC_TR_HU_Pos); + sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >> RTC_TR_MNU_Pos); + sTime->Seconds = (uint8_t)( tmpreg & (RTC_TR_ST | RTC_TR_SU)); + sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> RTC_TR_PM_Pos); + + /* Check the input parameters format */ + if (Format == RTC_FORMAT_BIN) + { + /* Convert the time structure parameters to Binary format */ + sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours); + sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes); + sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds); + } + + return HAL_OK; +} + +/** + * @brief Sets RTC current date. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sDate Pointer to date structure + * @param Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0U; + HAL_StatusTypeDef status; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + if ((Format == RTC_FORMAT_BIN) && ((sDate->Month & 0x10U) == 0x10U)) + { + sDate->Month = (uint8_t)((sDate->Month & (uint8_t)~(0x10U)) + (uint8_t)0x0AU); + } + + assert_param(IS_RTC_WEEKDAY(sDate->WeekDay)); + + if (Format == RTC_FORMAT_BIN) + { + assert_param(IS_RTC_YEAR(sDate->Year)); + assert_param(IS_RTC_MONTH(sDate->Month)); + assert_param(IS_RTC_DATE(sDate->Date)); + + datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year) << RTC_DR_YU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Month) << RTC_DR_MU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sDate->Date)) | \ + ((uint32_t)sDate->WeekDay << RTC_DR_WDU_Pos)); + } + else + { + assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year))); + assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month))); + assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date))); + + datetmpreg = ((((uint32_t)sDate->Year) << RTC_DR_YU_Pos) | \ + (((uint32_t)sDate->Month) << RTC_DR_MU_Pos) | \ + ((uint32_t) sDate->Date) | \ + (((uint32_t)sDate->WeekDay) << RTC_DR_WDU_Pos)); + } + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Set the RTC_DR register */ + hrtc->Instance->DR = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Gets RTC current date. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sDate Pointer to Date structure + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the + * values in the higher-order calendar shadow registers to ensure + * consistency between the time and date values. + * Reading RTC current time locks the values in calendar shadow registers + * until current date is read to ensure consistency between the time and + * date values. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format) +{ + uint32_t datetmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the DR register */ + datetmpreg = (uint32_t)(hrtc->Instance->DR & RTC_DR_RESERVED_MASK); + + /* Fill the structure fields with the read parameters */ + sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> RTC_DR_YU_Pos); + sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> RTC_DR_MU_Pos); + sDate->Date = (uint8_t) (datetmpreg & (RTC_DR_DT | RTC_DR_DU)); + sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> RTC_DR_WDU_Pos); + + /* Check the input parameters format */ + if (Format == RTC_FORMAT_BIN) + { + /* Convert the date structure parameters to Binary format */ + sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year); + sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month); + sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date); + } + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group3 RTC Alarm functions + * @brief RTC Alarm functions + * +@verbatim + =============================================================================== + ##### RTC Alarm functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Alarm feature + +@endverbatim + * @{ + */ +/** + * @brief Sets the specified RTC Alarm. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sAlarm Pointer to Alarm structure + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the HAL_RTC_DeactivateAlarm()). + * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + uint32_t tickstart = 0U; + uint32_t tmpreg = 0U; + uint32_t subsecondtmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + /* Change RTC state to BUSY */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Check the data format (binary or BCD) and store the Alarm time and date + configuration accordingly */ + if (Format == RTC_FORMAT_BIN) + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_TR_PM_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay))); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay))); + } + + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_TR_PM_Pos) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \ + ((uint32_t) sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t) sAlarm->AlarmMask)); + } + + /* Store the Alarm subseconds configuration */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | \ + (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if (sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case interrupt mode is used, the interrupt source must be disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRAWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Subseconds register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + } + else + { + /* Disable the Alarm B */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case interrupt mode is used, the interrupt source must be disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB); + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRBWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Subseconds register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state back to READY */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Sets the specified RTC Alarm with Interrupt. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sAlarm Pointer to Alarm structure + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use the HAL_RTC_DeactivateAlarm()). + * @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format) +{ + __IO uint32_t count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U); + uint32_t tmpreg = 0U; + uint32_t subsecondtmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(sAlarm->Alarm)); + assert_param(IS_RTC_ALARM_MASK(sAlarm->AlarmMask)); + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_SEL(sAlarm->AlarmDateWeekDaySel)); + assert_param(IS_RTC_ALARM_SUB_SECOND_VALUE(sAlarm->AlarmTime.SubSeconds)); + assert_param(IS_RTC_ALARM_SUB_SECOND_MASK(sAlarm->AlarmSubSecondMask)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + /* Change RTC state to BUSY */ + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Check the data format (binary or BCD) and store the Alarm time and date + configuration accordingly */ + if (Format == RTC_FORMAT_BIN) + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(sAlarm->AlarmTime.Hours)); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours)); + } + assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes)); + assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds)); + + if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(sAlarm->AlarmDateWeekDay)); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(sAlarm->AlarmDateWeekDay)); + } + + tmpreg = (((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds)) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_TR_PM_Pos) | \ + ((uint32_t)RTC_ByteToBcd2(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \ + ((uint32_t)sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t)sAlarm->AlarmMask)); + } + else + { + if ((hrtc->Instance->CR & RTC_CR_FMT) != 0U) + { + assert_param(IS_RTC_HOUR12(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + assert_param(IS_RTC_HOURFORMAT12(sAlarm->AlarmTime.TimeFormat)); + } + else + { + sAlarm->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours))); + } + + assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes))); + assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds))); + + if (sAlarm->AlarmDateWeekDaySel == RTC_ALARMDATEWEEKDAYSEL_DATE) + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_DATE(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay))); + } + else + { + assert_param(IS_RTC_ALARM_DATE_WEEKDAY_WEEKDAY(RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay))); + } + + tmpreg = (((uint32_t)(sAlarm->AlarmTime.Hours) << RTC_ALRMAR_HU_Pos) | \ + ((uint32_t)(sAlarm->AlarmTime.Minutes) << RTC_ALRMAR_MNU_Pos) | \ + ((uint32_t) sAlarm->AlarmTime.Seconds) | \ + ((uint32_t)(sAlarm->AlarmTime.TimeFormat) << RTC_TR_PM_Pos) | \ + ((uint32_t)(sAlarm->AlarmDateWeekDay) << RTC_ALRMAR_DU_Pos) | \ + ((uint32_t) sAlarm->AlarmDateWeekDaySel) | \ + ((uint32_t) sAlarm->AlarmMask)); + } + + /* Store the Alarm subseconds configuration */ + subsecondtmpreg = (uint32_t)((uint32_t)(sAlarm->AlarmTime.SubSeconds) | \ + (uint32_t)(sAlarm->AlarmSubSecondMask)); + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Configure the Alarm register */ + if (sAlarm->Alarm == RTC_ALARM_A) + { + /* Disable the Alarm A */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* Wait till RTC ALRAWF flag is set and if timeout is reached exit */ + do + { + if (count-- == 0U) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U); + + hrtc->Instance->ALRMAR = (uint32_t)tmpreg; + /* Configure the Alarm A Subseconds register */ + hrtc->Instance->ALRMASSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA); + } + else + { + /* Disable the Alarm B */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* Reload the counter */ + count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U); + + /* Wait till RTC ALRBWF flag is set and if timeout is reached exit */ + do + { + if (count-- == 0U) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U); + + hrtc->Instance->ALRMBR = (uint32_t)tmpreg; + /* Configure the Alarm B Subseconds register */ + hrtc->Instance->ALRMBSSR = subsecondtmpreg; + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMB_ENABLE(hrtc); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRB); + } + + /* RTC Alarm Interrupt Configuration: EXTI configuration */ + __HAL_RTC_ALARM_EXTI_ENABLE_IT(); + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state back to READY */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivates the specified RTC Alarm. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Alarm Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: Alarm A + * @arg RTC_ALARM_B: Alarm B + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_ALARM(Alarm)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + if (Alarm == RTC_ALARM_A) + { + /* Disable Alarm A */ + __HAL_RTC_ALARMA_DISABLE(hrtc); + + /* In case interrupt mode is used, the interrupt source must be disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + else + { + /* Disable Alarm B */ + __HAL_RTC_ALARMB_DISABLE(hrtc); + + /* In case interrupt mode is used, the interrupt source must be disabled */ + __HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRB); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRxWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Gets the RTC Alarm value and masks. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sAlarm Pointer to Date structure + * @param Alarm Specifies the Alarm. + * This parameter can be one of the following values: + * @arg RTC_ALARM_A: Alarm A + * @arg RTC_ALARM_B: Alarm B + * @param Format Specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format) +{ + uint32_t tmpreg = 0U; + uint32_t subsecondtmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + assert_param(IS_RTC_ALARM(Alarm)); + + if (Alarm == RTC_ALARM_A) + { + sAlarm->Alarm = RTC_ALARM_A; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMAR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMASSR) & RTC_ALRMASSR_SS); + } + else + { + sAlarm->Alarm = RTC_ALARM_B; + + tmpreg = (uint32_t)(hrtc->Instance->ALRMBR); + subsecondtmpreg = (uint32_t)((hrtc->Instance->ALRMBSSR) & RTC_ALRMBSSR_SS); + } + + /* Fill the structure with the read parameters */ + sAlarm->AlarmTime.Hours = (uint8_t) ((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> RTC_ALRMAR_HU_Pos); + sAlarm->AlarmTime.Minutes = (uint8_t) ((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> RTC_ALRMAR_MNU_Pos); + sAlarm->AlarmTime.Seconds = (uint8_t) ( tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU)); + sAlarm->AlarmTime.TimeFormat = (uint8_t) ((tmpreg & RTC_ALRMAR_PM) >> RTC_TR_PM_Pos); + sAlarm->AlarmTime.SubSeconds = (uint32_t) subsecondtmpreg; + sAlarm->AlarmDateWeekDay = (uint8_t) ((tmpreg & (RTC_ALRMAR_DT | RTC_ALRMAR_DU)) >> RTC_ALRMAR_DU_Pos); + sAlarm->AlarmDateWeekDaySel = (uint32_t) (tmpreg & RTC_ALRMAR_WDSEL); + sAlarm->AlarmMask = (uint32_t) (tmpreg & RTC_ALARMMASK_ALL); + + if (Format == RTC_FORMAT_BIN) + { + sAlarm->AlarmTime.Hours = RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours); + sAlarm->AlarmTime.Minutes = RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes); + sAlarm->AlarmTime.Seconds = RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds); + sAlarm->AlarmDateWeekDay = RTC_Bcd2ToByte(sAlarm->AlarmDateWeekDay); + } + + return HAL_OK; +} + +/** + * @brief Handles Alarm interrupt request. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Get the Alarm A interrupt source enable status */ + if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA) != 0U) + { + /* Get the pending status of the Alarm A Interrupt */ + if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != 0U) + { + /* Alarm A callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->AlarmAEventCallback(hrtc); +#else + HAL_RTC_AlarmAEventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Alarm A interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + } + } + + /* Get the Alarm B interrupt source enable status */ + if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRB) != 0U) + { + /* Get the pending status of the Alarm B Interrupt */ + if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) != 0U) + { + /* Alarm B callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->AlarmBEventCallback(hrtc); +#else + HAL_RTCEx_AlarmBEventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Alarm B interrupt pending bit */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + } + } + + /* Clear the EXTI's line Flag for RTC Alarm */ + __HAL_RTC_ALARM_EXTI_CLEAR_FLAG(); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Alarm A callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTC_AlarmAEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handles Alarm A Polling request. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRAF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group4 Peripheral Control functions + * @brief Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Wait for RTC Time and Date Synchronization + (+) Manage RTC Summer or Winter time change + +@endverbatim + * @{ + */ + +/** + * @brief Waits until the RTC Time and Date registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @note To read the calendar through the shadow registers after Calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TR and RTC_DR shadow registers. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0U; + + /* Clear RSF flag */ + hrtc->Instance->ISR &= (uint32_t)RTC_RSF_MASK; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait the registers to be synchronised */ + while ((hrtc->Instance->ISR & RTC_ISR_RSF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + return HAL_TIMEOUT; + } + } + + return HAL_OK; +} + +/** + * @brief Daylight Saving Time, adds one hour to the calendar in one + * single operation without going through the initialization procedure. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTC_DST_Add1Hour(RTC_HandleTypeDef *hrtc) +{ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + SET_BIT(hrtc->Instance->CR, RTC_CR_ADD1H); + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); +} + +/** + * @brief Daylight Saving Time, subtracts one hour from the calendar in one + * single operation without going through the initialization procedure. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTC_DST_Sub1Hour(RTC_HandleTypeDef *hrtc) +{ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + SET_BIT(hrtc->Instance->CR, RTC_CR_SUB1H); + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); +} + +/** + * @brief Daylight Saving Time, sets the store operation bit. + * @note It can be used by the software in order to memorize the DST status. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTC_DST_SetStoreOperation(RTC_HandleTypeDef *hrtc) +{ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + SET_BIT(hrtc->Instance->CR, RTC_CR_BKP); + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); +} + +/** + * @brief Daylight Saving Time, clears the store operation bit. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTC_DST_ClearStoreOperation(RTC_HandleTypeDef *hrtc) +{ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + CLEAR_BIT(hrtc->Instance->CR, RTC_CR_BKP); + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); +} + +/** + * @brief Daylight Saving Time, reads the store operation bit. + * @param hrtc RTC handle + * @retval operation see RTC_StoreOperation_Definitions + */ +uint32_t HAL_RTC_DST_ReadStoreOperation(RTC_HandleTypeDef *hrtc) +{ + return READ_BIT(hrtc->Instance->CR, RTC_CR_BKP); +} + +/** + * @} + */ + +/** @defgroup RTC_Exported_Functions_Group5 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Get RTC state + +@endverbatim + * @{ + */ +/** + * @brief Returns the RTC state. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL state + */ +HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc) +{ + return hrtc->State; +} + +/** + * @} + */ + + +/** + * @} + */ + +/** @addtogroup RTC_Private_Functions + * @{ + */ + +/** + * @brief Enters the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * __HAL_RTC_WRITEPROTECTION_DISABLE() before calling this function. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0U; + HAL_StatusTypeDef status = HAL_OK; + + /* Check that Initialization mode is not already set */ + if (READ_BIT(hrtc->Instance->ISR, RTC_ISR_INITF) == 0U) + { + /* Set INIT bit to enter Initialization mode */ + SET_BIT(hrtc->Instance->ISR, RTC_ISR_INIT); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC is in INIT state and if timeout is reached exit */ + while ((READ_BIT(hrtc->Instance->ISR, RTC_ISR_INITF) == 0U) && (status != HAL_ERROR)) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + status = HAL_ERROR; + } + } + } + + return status; +} + +/** + * @brief Exits the RTC Initialization mode. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Clear INIT bit to exit Initialization mode */ + CLEAR_BIT(hrtc->Instance->ISR, RTC_ISR_INIT); + + /* If CR_BYPSHAD bit = 0, wait for synchro */ + if (READ_BIT(hrtc->Instance->CR, RTC_CR_BYPSHAD) == 0U) + { + if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Set RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + status = HAL_ERROR; + } + } + + return status; +} + +/** + * @brief Converts a 2-digit number from decimal to BCD format. + * @param number decimal-formatted number (from 0 to 99) to be converted + * @retval Converted byte + */ +uint8_t RTC_ByteToBcd2(uint8_t number) +{ + uint8_t bcdhigh = 0U; + + while (number >= 10U) + { + bcdhigh++; + number -= 10U; + } + + return ((uint8_t)(bcdhigh << 4U) | number); +} + +/** + * @brief Converts a 2-digit number from BCD to decimal format. + * @param number BCD-formatted number (from 00 to 99) to be converted + * @retval Converted word + */ +uint8_t RTC_Bcd2ToByte(uint8_t number) +{ + uint8_t tmp = 0U; + tmp = ((uint8_t)(number & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; + return (tmp + (number & (uint8_t)0x0F)); +} + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c new file mode 100644 index 0000000..eb5708f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_rtc_ex.c @@ -0,0 +1,1878 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_rtc_ex.c + * @author MCD Application Team + * @brief Extended RTC HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Real-Time Clock (RTC) Extended peripheral: + * + RTC Timestamp functions + * + RTC Tamper functions + * + RTC Wakeup functions + * + Extended Control functions + * + Extended RTC features functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + (+) Enable the RTC domain access. + (+) Configure the RTC Prescaler (Asynchronous and Synchronous) and RTC hour + format using the HAL_RTC_Init() function. + + *** RTC Wakeup configuration *** + ================================ + [..] + (+) To configure the RTC Wakeup Clock source and Counter use the + HAL_RTCEx_SetWakeUpTimer() function. + You can also configure the RTC Wakeup timer in interrupt mode using the + HAL_RTCEx_SetWakeUpTimer_IT() function. + (+) To read the RTC Wakeup Counter register, use the HAL_RTCEx_GetWakeUpTimer() + function. + + *** Timestamp configuration *** + =============================== + [..] + (+) To configure the RTC Timestamp use the HAL_RTCEx_SetTimeStamp() function. + You can also configure the RTC Timestamp with interrupt mode using the + HAL_RTCEx_SetTimeStamp_IT() function. + (+) To read the RTC Timestamp Time and Date register, use the + HAL_RTCEx_GetTimeStamp() function. + (+) The Timestamp alternate function can be mapped either to RTC_AF1 (PC13) + or RTC_AF2 (PI8) depending on the value of TSINSEL bit in RTC_TAFCR + register. + For STM32F446xx devices RTC_AF2 corresponds to pin PA0 and not to pin PI8. + The corresponding pin is also selected by HAL_RTCEx_SetTimeStamp() + or HAL_RTCEx_SetTimeStamp_IT() functions. + + *** Tamper configuration *** + ============================ + [..] + (+) To Enable the RTC Tamper and configure the Tamper filter count, trigger + Edge or Level according to the Tamper filter value (if equal to 0 Edge + else Level), sampling frequency, precharge or discharge and Pull-UP use + the HAL_RTCEx_SetTamper() function. + You can configure RTC Tamper in interrupt mode using HAL_RTCEx_SetTamper_IT() + function. + (+) The TAMPER1 alternate function can be mapped either to RTC_AF1 (PC13) + or RTC_AF2 (PI8) depending on the value of TAMP1INSEL bit in RTC_TAFCR + register. + The corresponding pin is also selected by HAL_RTCEx_SetTamper() + or HAL_RTCEx_SetTamper_IT() functions. + (+) The TAMPER2 alternate function is mapped to RTC_AF2 (PI8). + For STM32F446xx devices RTC_AF2 corresponds to pin PA0 and not to pin PI8. + + *** Backup Data Registers configuration *** + =========================================== + [..] + (+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite() + function. + (+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead() + function. + + *** Coarse Digital Calibration configuration *** + ================================================ + [..] + (+) The Coarse Digital Calibration can be used to compensate crystal inaccuracy + by setting the DCS bit in RTC_CALIBR register. + (+) When positive calibration is enabled (DCS = ‘0’), 2 asynchronous prescaler + clock cycles are added every minute during 2xDC minutes. + This causes the calendar to be updated sooner, thereby adjusting the + effective RTC frequency to be a bit higher. + (+) When negative calibration is enabled (DCS = ‘1’), 1 asynchronous prescaler + clock cycle is removed every minute during 2xDC minutes. + This causes the calendar to be updated later, thereby adjusting the + effective RTC frequency to be a bit lower. + (+) DC is configured through bits DC[4:0] of RTC_CALIBR register. This number + ranges from 0 to 31 corresponding to a time interval (2xDC) ranging from + 0 to 62. + (+) In order to measure the clock deviation, a 512 Hz clock is output for + calibration. + (+) The RTC Coarse Digital Calibration value and sign can be calibrated using + the HAL_RTCEx_SetCoarseCalib() function. + + *** Smooth Digital Calibration configuration *** + ================================================ + [..] + (+) RTC frequency can be digitally calibrated with a resolution of about + 0.954 ppm with a range from -487.1 ppm to +488.5 ppm. + The correction of the frequency is performed using a series of small + adjustments (adding and/or subtracting individual RTCCLK pulses). + (+) The smooth digital calibration is performed during a cycle of about 2^20 + RTCCLK pulses (or 32 seconds) when the input frequency is 32,768 Hz. + This cycle is maintained by a 20-bit counter clocked by RTCCLK. + (+) The smooth calibration register (RTC_CALR) specifies the number of RTCCLK + clock cycles to be masked during the 32-second cycle. + (+) The RTC Smooth Digital Calibration value and the corresponding calibration + cycle period (32s, 16s, or 8s) can be calibrated using the + HAL_RTCEx_SetSmoothCalib() function. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup RTCEx RTCEx + * @brief RTC Extended HAL module driver + * @{ + */ + +#ifdef HAL_RTC_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions + * @{ + */ + +/** @defgroup RTCEx_Exported_Functions_Group1 RTC Timestamp and Tamper functions + * @brief RTC Timestamp and Tamper functions + * +@verbatim + =============================================================================== + ##### RTC Timestamp and Tamper functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Timestamp feature + +@endverbatim + * @{ + */ + +/** + * @brief Sets Timestamp. + * @note This API must be called before enabling the Timestamp feature. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param RTC_TimeStampEdge Specifies the pin edge on which the Timestamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Timestamp event occurs on + * the rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Timestamp event occurs on + * the falling edge of the related pin. + * @param RTC_TimeStampPin Specifies the RTC Timestamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC Timestamp Pin. + * @arg RTC_TIMESTAMPPIN_POS1: PI8 is selected as RTC Timestamp Pin. + * @note RTC_TIMESTAMPPIN_POS1 corresponds to pin PA0 in the case of + * STM32F446xx devices. + * @note RTC_TIMESTAMPPIN_POS1 is not applicable to the following list of devices: + * STM32F412xx, STM32F413xx and STM32F423xx. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(RTC_TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + /* Change RTC state to BUSY */ + hrtc->State = HAL_RTC_STATE_BUSY; + + hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_TSINSEL; + hrtc->Instance->TAFCR |= (uint32_t)(RTC_TimeStampPin); + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + /* Configure the Timestamp TSEDGE bit */ + tmpreg |= RTC_TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Copy the desired configuration into the CR register */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + /* Clear RTC Timestamp flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + + /* Clear RTC Timestamp overrun Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF); + + /* Enable the Timestamp saving */ + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state back to READY */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Sets Timestamp with Interrupt. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @note This API must be called before enabling the Timestamp feature. + * @param RTC_TimeStampEdge Specifies the pin edge on which the Timestamp is + * activated. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPEDGE_RISING: the Timestamp event occurs on + * the rising edge of the related pin. + * @arg RTC_TIMESTAMPEDGE_FALLING: the Timestamp event occurs on + * the falling edge of the related pin. + * @param RTC_TimeStampPin Specifies the RTC Timestamp Pin. + * This parameter can be one of the following values: + * @arg RTC_TIMESTAMPPIN_DEFAULT: PC13 is selected as RTC Timestamp Pin. + * @arg RTC_TIMESTAMPPIN_POS1: PI8 is selected as RTC Timestamp Pin. + * @note RTC_TIMESTAMPPIN_POS1 corresponds to pin PA0 in the case of + * STM32F446xx devices. + * @note RTC_TIMESTAMPPIN_POS1 is not applicable to the following list of devices: + * STM32F412xx, STM32F413xx and STM32F423xx. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTimeStamp_IT(RTC_HandleTypeDef *hrtc, uint32_t RTC_TimeStampEdge, uint32_t RTC_TimeStampPin) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_TIMESTAMP_EDGE(RTC_TimeStampEdge)); + assert_param(IS_RTC_TIMESTAMP_PIN(RTC_TimeStampPin)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + /* Change RTC state to BUSY */ + hrtc->State = HAL_RTC_STATE_BUSY; + + hrtc->Instance->TAFCR &= (uint32_t)~RTC_TAFCR_TSINSEL; + hrtc->Instance->TAFCR |= (uint32_t)(RTC_TimeStampPin); + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + /* Configure the Timestamp TSEDGE bit */ + tmpreg |= RTC_TimeStampEdge; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Copy the desired configuration into the CR register */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + /* Clear RTC Timestamp flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + + /* Clear RTC Timestamp overrun Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF); + + /* Enable the Timestamp saving */ + __HAL_RTC_TIMESTAMP_ENABLE(hrtc); + + /* Enable IT Timestamp */ + __HAL_RTC_TIMESTAMP_ENABLE_IT(hrtc, RTC_IT_TS); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* RTC Timestamp Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + /* Change RTC state back to READY */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivates Timestamp. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTimeStamp(RTC_HandleTypeDef *hrtc) +{ + uint32_t tmpreg = 0U; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_TIMESTAMP_DISABLE_IT(hrtc, RTC_IT_TS); + + /* Get the RTC_CR register and clear the bits to be configured */ + tmpreg = (uint32_t)(hrtc->Instance->CR & (uint32_t)~(RTC_CR_TSEDGE | RTC_CR_TSE)); + + /* Configure the Timestamp TSEDGE and Enable bits */ + hrtc->Instance->CR = (uint32_t)tmpreg; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Gets the RTC Timestamp value. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sTimeStamp Pointer to Time structure + * @param sTimeStampDate Pointer to Date structure + * @param Format specifies the format of the entered parameters. + * This parameter can be one of the following values: + * @arg RTC_FORMAT_BIN: Binary data format + * @arg RTC_FORMAT_BCD: BCD data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_GetTimeStamp(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTimeStamp, RTC_DateTypeDef *sTimeStampDate, uint32_t Format) +{ + uint32_t tmptime = 0U; + uint32_t tmpdate = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_FORMAT(Format)); + + /* Get the Timestamp time and date registers values */ + tmptime = (uint32_t)(hrtc->Instance->TSTR & RTC_TR_RESERVED_MASK); + tmpdate = (uint32_t)(hrtc->Instance->TSDR & RTC_DR_RESERVED_MASK); + + /* Fill the Time structure fields with the read parameters */ + sTimeStamp->Hours = (uint8_t)((tmptime & (RTC_TSTR_HT | RTC_TSTR_HU)) >> RTC_TSTR_HU_Pos); + sTimeStamp->Minutes = (uint8_t)((tmptime & (RTC_TSTR_MNT | RTC_TSTR_MNU)) >> RTC_TSTR_MNU_Pos); + sTimeStamp->Seconds = (uint8_t)((tmptime & (RTC_TSTR_ST | RTC_TSTR_SU)) >> RTC_TSTR_SU_Pos); + sTimeStamp->TimeFormat = (uint8_t)((tmptime & (RTC_TSTR_PM)) >> RTC_TSTR_PM_Pos); + sTimeStamp->SubSeconds = (uint32_t) hrtc->Instance->TSSSR; + + /* Fill the Date structure fields with the read parameters */ + sTimeStampDate->Year = 0U; + sTimeStampDate->Month = (uint8_t)((tmpdate & (RTC_TSDR_MT | RTC_TSDR_MU)) >> RTC_TSDR_MU_Pos); + sTimeStampDate->Date = (uint8_t)((tmpdate & (RTC_TSDR_DT | RTC_TSDR_DU)) >> RTC_TSDR_DU_Pos); + sTimeStampDate->WeekDay = (uint8_t)((tmpdate & (RTC_TSDR_WDU)) >> RTC_TSDR_WDU_Pos); + + /* Check the input parameters format */ + if (Format == RTC_FORMAT_BIN) + { + /* Convert the Timestamp structure parameters to Binary format */ + sTimeStamp->Hours = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Hours); + sTimeStamp->Minutes = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Minutes); + sTimeStamp->Seconds = (uint8_t)RTC_Bcd2ToByte(sTimeStamp->Seconds); + + /* Convert the DateTimeStamp structure parameters to Binary format */ + sTimeStampDate->Month = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Month); + sTimeStampDate->Date = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->Date); + sTimeStampDate->WeekDay = (uint8_t)RTC_Bcd2ToByte(sTimeStampDate->WeekDay); + } + + /* Clear the Timestamp Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + + return HAL_OK; +} + +/** + * @brief Sets Tamper. + * @note By calling this API the tamper global interrupt will be disabled. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sTamper Pointer to Tamper Structure. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_PIN(sTamper->PinSelection)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Copy control register into temporary variable */ + tmpreg = hrtc->Instance->TAFCR; + + /* Enable selected tamper */ + tmpreg |= (sTamper->Tamper); + + /* Configure the tamper trigger bit (this bit is just on the right of the + tamper enable bit, hence the one-time right shift before updating it) */ + if (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE) + { + /* Set the tamper trigger bit (case of falling edge or high level) */ + tmpreg |= (uint32_t)(sTamper->Tamper << 1U); + } + else + { + /* Clear the tamper trigger bit (case of rising edge or low level) */ + tmpreg &= (uint32_t)~(sTamper->Tamper << 1U); + } + + /* Clear remaining fields before setting them */ + tmpreg &= ~(RTC_TAMPERFILTER_MASK | \ + RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \ + RTC_TAMPERPRECHARGEDURATION_MASK | \ + RTC_TAMPER_PULLUP_MASK | \ + RTC_TAFCR_TAMP1INSEL | \ + RTC_TIMESTAMPONTAMPERDETECTION_MASK); + + /* Set remaining parameters of desired configuration into temporary variable */ + tmpreg |= ((uint32_t)sTamper->Filter | \ + (uint32_t)sTamper->SamplingFrequency | \ + (uint32_t)sTamper->PrechargeDuration | \ + (uint32_t)sTamper->TamperPullUp | \ + (uint32_t)sTamper->PinSelection | \ + (uint32_t)sTamper->TimeStampOnTamperDetection); + + /* Disable tamper global interrupt in case it is enabled */ + tmpreg &= (uint32_t)~RTC_TAFCR_TAMPIE; + + /* Copy desired configuration into configuration register */ + hrtc->Instance->TAFCR = tmpreg; + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Sets Tamper with interrupt. + * @note By calling this API the tamper global interrupt will be enabled. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param sTamper Pointer to RTC Tamper. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper) +{ + uint32_t tmpreg = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_TAMPER(sTamper->Tamper)); + assert_param(IS_RTC_TAMPER_PIN(sTamper->PinSelection)); + assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_FILTER(sTamper->Filter)); + assert_param(IS_RTC_TAMPER_FILTER_CONFIG_CORRECT(sTamper->Filter, sTamper->Trigger)); + assert_param(IS_RTC_TAMPER_SAMPLING_FREQ(sTamper->SamplingFrequency)); + assert_param(IS_RTC_TAMPER_PRECHARGE_DURATION(sTamper->PrechargeDuration)); + assert_param(IS_RTC_TAMPER_PULLUP_STATE(sTamper->TamperPullUp)); + assert_param(IS_RTC_TAMPER_TIMESTAMPONTAMPER_DETECTION(sTamper->TimeStampOnTamperDetection)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Copy control register into temporary variable */ + tmpreg = hrtc->Instance->TAFCR; + + /* Enable selected tamper */ + tmpreg |= (sTamper->Tamper); + + /* Configure the tamper trigger bit (this bit is just on the right of the + tamper enable bit, hence the one-time right shift before updating it) */ + if (sTamper->Trigger == RTC_TAMPERTRIGGER_FALLINGEDGE) + { + /* Set the tamper trigger bit (case of falling edge or high level) */ + tmpreg |= (uint32_t)(sTamper->Tamper << 1U); + } + else + { + /* Clear the tamper trigger bit (case of rising edge or low level) */ + tmpreg &= (uint32_t)~(sTamper->Tamper << 1U); + } + + /* Clear remaining fields before setting them */ + tmpreg &= ~(RTC_TAMPERFILTER_MASK | \ + RTC_TAMPERSAMPLINGFREQ_RTCCLK_MASK | \ + RTC_TAMPERPRECHARGEDURATION_MASK | \ + RTC_TAMPER_PULLUP_MASK | \ + RTC_TAFCR_TAMP1INSEL | \ + RTC_TIMESTAMPONTAMPERDETECTION_MASK); + + /* Set remaining parameters of desired configuration into temporary variable */ + tmpreg |= ((uint32_t)sTamper->Filter | \ + (uint32_t)sTamper->SamplingFrequency | \ + (uint32_t)sTamper->PrechargeDuration | \ + (uint32_t)sTamper->TamperPullUp | \ + (uint32_t)sTamper->PinSelection | \ + (uint32_t)sTamper->TimeStampOnTamperDetection); + + /* Enable global tamper interrupt */ + tmpreg |= (uint32_t)RTC_TAFCR_TAMPIE; + + /* Copy desired configuration into configuration register */ + hrtc->Instance->TAFCR = tmpreg; + + /* RTC Tamper Interrupt Configuration: EXTI configuration */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_IT(); + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_ENABLE_RISING_EDGE(); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivates Tamper. + * @note The tamper global interrupt bit will remain unchanged. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Tamper Selected tamper pin. + * This parameter can be any combination of the following values: + * @arg RTC_TAMPER_1: Tamper 1 + * @arg RTC_TAMPER_2: Tamper 2 + * @note RTC_TAMPER_2 is not applicable to all devices. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper) +{ + assert_param(IS_RTC_TAMPER(Tamper)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the selected Tamper pin */ + hrtc->Instance->TAFCR &= (uint32_t)~Tamper; + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Handles Timestamp and Tamper interrupt request. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTCEx_TamperTimeStampIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Get the Timestamp interrupt source enable status */ + if (__HAL_RTC_TIMESTAMP_GET_IT_SOURCE(hrtc, RTC_IT_TS) != 0U) + { + /* Get the pending status of the Timestamp Interrupt */ + if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) != 0U) + { + /* Timestamp callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->TimeStampEventCallback(hrtc); +#else + HAL_RTCEx_TimeStampEventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Timestamp interrupt pending bit */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSF); + } + } + + /* Get the Tamper 1 interrupt source enable status */ + if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP) != 0U) + { + /* Get the pending status of the Tamper 1 Interrupt */ + if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != 0U) + { + /* Tamper callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->Tamper1EventCallback(hrtc); +#else + HAL_RTCEx_Tamper1EventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Tamper interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + } + } + +#if defined(RTC_TAMPER2_SUPPORT) + /* Get the Tamper 2 interrupt source enable status */ + if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP) != 0U) + { + /* Get the pending status of the Tamper 2 Interrupt */ + if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) != 0U) + { + /* Tamper callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->Tamper2EventCallback(hrtc); +#else + HAL_RTCEx_Tamper2EventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Tamper interrupt pending bit */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + } + } +#endif /* RTC_TAMPER2_SUPPORT */ + + /* Clear the EXTI's Flag for RTC Timestamp and Tamper */ + __HAL_RTC_TAMPER_TIMESTAMP_EXTI_CLEAR_FLAG(); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Timestamp callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTCEx_TimeStampEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTCEx_TimeStampEventCallback could be implemented in the user file + */ +} + +/** + * @brief Tamper 1 callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file + */ +} + +#if defined(RTC_TAMPER2_SUPPORT) +/** + * @brief Tamper 2 callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTCEx_Tamper2EventCallback could be implemented in the user file + */ +} +#endif /* RTC_TAMPER2_SUPPORT */ + +/** + * @brief Handles Timestamp polling request. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTimeStampEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + while (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSF) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + + if (__HAL_RTC_TIMESTAMP_GET_FLAG(hrtc, RTC_FLAG_TSOVF) != 0U) + { + /* Clear the Timestamp Overrun Flag */ + __HAL_RTC_TIMESTAMP_CLEAR_FLAG(hrtc, RTC_FLAG_TSOVF); + + /* Change Timestamp state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + return HAL_ERROR; + } + } + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Handles Tamper 1 Polling. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +#if defined(RTC_TAMPER2_SUPPORT) +/** + * @brief Handles Tamper 2 Polling. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForTamper2Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Get the status of the Interrupt */ + while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP2F) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Tamper Flag */ + __HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP2F); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} +#endif /* RTC_TAMPER2_SUPPORT */ + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group2 RTC Wakeup functions + * @brief RTC Wakeup functions + * +@verbatim + =============================================================================== + ##### RTC Wakeup functions ##### + =============================================================================== + + [..] This section provides functions allowing to configure Wakeup feature + +@endverbatim + * @{ + */ + +/** + * @brief Sets wakeup timer. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param WakeUpCounter Wakeup counter + * @param WakeUpClock Wakeup clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Check RTC WUTWF flag is reset only when wakeup timer enabled*/ + if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U) + { + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is reset and if timeout is reached exit */ + while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + /* Disable the Wakeup timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* Clear the Wakeup flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Sets wakeup timer with interrupt. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param WakeUpCounter Wakeup counter + * @param WakeUpClock Wakeup clock + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock) +{ + __IO uint32_t count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U); + + /* Check the parameters */ + assert_param(IS_RTC_WAKEUP_CLOCK(WakeUpClock)); + assert_param(IS_RTC_WAKEUP_COUNTER(WakeUpCounter)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Check RTC WUTWF flag is reset only when wakeup timer enabled */ + if ((hrtc->Instance->CR & RTC_CR_WUTE) != 0U) + { + /* Wait till RTC WUTWF flag is reset and if timeout is reached exit */ + do + { + if (count-- == 0U) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) != 0U); + } + + /* Disable the Wakeup timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* Clear the Wakeup flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* Reload the counter */ + count = RTC_TIMEOUT_VALUE * (SystemCoreClock / 32U / 1000U); + + /* Wait till RTC WUTWF flag is set and if timeout is reached exit */ + do + { + if (count-- == 0U) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U); + + /* Clear the Wakeup Timer clock source bits in CR register */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hrtc->Instance->CR |= (uint32_t)WakeUpClock; + + /* Configure the Wakeup Timer counter */ + hrtc->Instance->WUTR = (uint32_t)WakeUpCounter; + + /* RTC wakeup timer Interrupt Configuration: EXTI configuration */ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT(); + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); + + /* Configure the interrupt in the RTC_CR register */ + __HAL_RTC_WAKEUPTIMER_ENABLE_IT(hrtc, RTC_IT_WUT); + + /* Enable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivates wakeup timer counter. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + uint32_t tickstart = 0U; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Disable the Wakeup Timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(hrtc); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_WAKEUPTIMER_DISABLE_IT(hrtc, RTC_IT_WUT); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC WUTWF flag is set and if timeout is reached exit */ + while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTWF) == 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Gets wakeup timer counter. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval Counter value + */ +uint32_t HAL_RTCEx_GetWakeUpTimer(RTC_HandleTypeDef *hrtc) +{ + /* Get the counter value */ + return ((uint32_t)(hrtc->Instance->WUTR & RTC_WUTR_WUT)); +} + +/** + * @brief Handles Wakeup Timer interrupt request. + * @note Unlike alarm interrupt line (shared by Alarms A and B) or tamper + * interrupt line (shared by timestamp and tampers) wakeup timer + * interrupt line is exclusive to the wakeup timer. + * There is no need in this case to check on the interrupt enable + * status via __HAL_RTC_WAKEUPTIMER_GET_IT_SOURCE(). + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +void HAL_RTCEx_WakeUpTimerIRQHandler(RTC_HandleTypeDef *hrtc) +{ + /* Get the pending status of the Wakeup timer Interrupt */ + if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) != 0U) + { + /* Wakeup timer callback */ +#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1) + hrtc->WakeUpTimerEventCallback(hrtc); +#else + HAL_RTCEx_WakeUpTimerEventCallback(hrtc); +#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */ + + /* Clear the Wakeup timer interrupt pending bit */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + } + + /* Clear the EXTI's line Flag for RTC WakeUpTimer */ + __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; +} + +/** + * @brief Wakeup Timer callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTCEx_WakeUpTimerEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handles Wakeup Timer Polling. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForWakeUpTimerEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(hrtc, RTC_FLAG_WUTF) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Wakeup timer Flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions + * @brief Extended Peripheral Control functions + * +@verbatim + =============================================================================== + ##### Extended Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides functions allowing to + (+) Write a data in a specified RTC Backup data register + (+) Read a data in a specified RTC Backup data register + (+) Set the Coarse calibration parameters. + (+) Deactivate the Coarse calibration parameters + (+) Set the Smooth calibration parameters. + (+) Configure the Synchronization Shift Control Settings. + (+) Configure the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Deactivate the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + (+) Enable the RTC reference clock detection. + (+) Disable the RTC reference clock detection. + (+) Enable the Bypass Shadow feature. + (+) Disable the Bypass Shadow feature. + +@endverbatim + * @{ + */ + +/** + * @brief Writes a data in a specified RTC Backup data register. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param BackupRegister RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx (where x can be from 0 to 19) + * to specify the register. + * @param Data Data to be written in the specified RTC Backup data register. + * @retval None + */ +void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data) +{ + uint32_t tmp = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t) & (hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4U); + + /* Write the specified register */ + *(__IO uint32_t *)tmp = (uint32_t)Data; +} + +/** + * @brief Reads data from the specified RTC Backup data Register. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param BackupRegister RTC Backup data Register number. + * This parameter can be: RTC_BKP_DRx (where x can be from 0 to 19) + * to specify the register. + * @retval Read value + */ +uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister) +{ + uint32_t tmp = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_BKP(BackupRegister)); + + tmp = (uint32_t) & (hrtc->Instance->BKP0R); + tmp += (BackupRegister * 4U); + + /* Read the specified register */ + return (*(__IO uint32_t *)tmp); +} + +/** + * @brief Sets the Coarse calibration parameters. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param CalibSign Specifies the sign of the coarse calibration value. + * This parameter can be one of the following values: + * @arg RTC_CALIBSIGN_POSITIVE: The value sign is positive + * @arg RTC_CALIBSIGN_NEGATIVE: The value sign is negative + * @param Value value of coarse calibration expressed in ppm (coded on 5 bits). + * + * @note This Calibration value should be between 0 and 63 when using negative + * sign with a 2-ppm step. + * + * @note This Calibration value should be between 0 and 126 when using positive + * sign with a 4-ppm step. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetCoarseCalib(RTC_HandleTypeDef *hrtc, uint32_t CalibSign, uint32_t Value) +{ + HAL_StatusTypeDef status; + + /* Check the parameters */ + assert_param(IS_RTC_CALIB_SIGN(CalibSign)); + assert_param(IS_RTC_CALIB_VALUE(Value)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Enable the Coarse Calibration */ + __HAL_RTC_COARSE_CALIB_ENABLE(hrtc); + + /* Set the coarse calibration value */ + hrtc->Instance->CALIBR = (uint32_t)(CalibSign | Value); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Deactivates the Coarse calibration parameters. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateCoarseCalib(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Disable the Coarse Calibration */ + __HAL_RTC_COARSE_CALIB_DISABLE(hrtc); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Sets the Smooth calibration parameters. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param SmoothCalibPeriod Select the Smooth Calibration Period. + * This parameter can be can be one of the following values: + * @arg RTC_SMOOTHCALIB_PERIOD_32SEC: The smooth calibration period is 32s. + * @arg RTC_SMOOTHCALIB_PERIOD_16SEC: The smooth calibration period is 16s. + * @arg RTC_SMOOTHCALIB_PERIOD_8SEC: The smooth calibration period is 8s. + * @param SmoothCalibPlusPulses Select to Set or reset the CALP bit. + * This parameter can be one of the following values: + * @arg RTC_SMOOTHCALIB_PLUSPULSES_SET: Add one RTCCLK pulse every 2*11 pulses. + * @arg RTC_SMOOTHCALIB_PLUSPULSES_RESET: No RTCCLK pulses are added. + * @param SmoothCalibMinusPulsesValue Select the value of CALM[8:0] bits. + * This parameter can be one any value from 0 to 0x000001FF. + * @note To deactivate the smooth calibration, the field SmoothCalibPlusPulses + * must be equal to SMOOTHCALIB_PLUSPULSES_RESET and the field + * SmoothCalibMinusPulsesValue must be equal to 0. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmoothCalibMinusPulsesValue) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_SMOOTH_CALIB_PERIOD(SmoothCalibPeriod)); + assert_param(IS_RTC_SMOOTH_CALIB_PLUS(SmoothCalibPlusPulses)); + assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmoothCalibMinusPulsesValue)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* check if a calibration is pending*/ + if ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* check if a calibration is pending*/ + while ((hrtc->Instance->ISR & RTC_ISR_RECALPF) != 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + } + + /* Configure the Smooth calibration settings */ + hrtc->Instance->CALR = (uint32_t)((uint32_t)SmoothCalibPeriod | \ + (uint32_t)SmoothCalibPlusPulses | \ + (uint32_t)SmoothCalibMinusPulsesValue); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configures the Synchronization Shift Control Settings. + * @note When REFCKON is set, firmware must not write to Shift control register. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param ShiftAdd1S Select to add or not 1 second to the time calendar. + * This parameter can be one of the following values: + * @arg RTC_SHIFTADD1S_SET: Add one second to the clock calendar. + * @arg RTC_SHIFTADD1S_RESET: No effect. + * @param ShiftSubFS Select the number of Second Fractions to substitute. + * This parameter can be one any value from 0 to 0x7FFF. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetSynchroShift(RTC_HandleTypeDef *hrtc, uint32_t ShiftAdd1S, uint32_t ShiftSubFS) +{ + uint32_t tickstart = 0U; + + /* Check the parameters */ + assert_param(IS_RTC_SHIFT_ADD1S(ShiftAdd1S)); + assert_param(IS_RTC_SHIFT_SUBFS(ShiftSubFS)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until the shift is completed */ + while ((hrtc->Instance->ISR & RTC_ISR_SHPF) != 0U) + { + if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_TIMEOUT; + } + } + + /* Check if the reference clock detection is disabled */ + if ((hrtc->Instance->CR & RTC_CR_REFCKON) == 0U) + { + /* Configure the Shift settings */ + hrtc->Instance->SHIFTR = (uint32_t)(uint32_t)(ShiftSubFS) | (uint32_t)(ShiftAdd1S); + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if ((hrtc->Instance->CR & RTC_CR_BYPSHAD) == 0U) + { + if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK) + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + } + } + else + { + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_ERROR; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Configures the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param CalibOutput Select the Calibration output Selection. + * This parameter can be one of the following values: + * @arg RTC_CALIBOUTPUT_512HZ: A signal has a regular waveform at 512Hz. + * @arg RTC_CALIBOUTPUT_1HZ: A signal has a regular waveform at 1Hz. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetCalibrationOutPut(RTC_HandleTypeDef *hrtc, uint32_t CalibOutput) +{ + /* Check the parameters */ + assert_param(IS_RTC_CALIB_OUTPUT(CalibOutput)); + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Clear flags before config */ + hrtc->Instance->CR &= (uint32_t)~RTC_CR_COSEL; + + /* Configure the RTC_CR register */ + hrtc->Instance->CR |= (uint32_t)CalibOutput; + + __HAL_RTC_CALIBRATION_OUTPUT_ENABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Deactivates the Calibration Pinout (RTC_CALIB) Selection (1Hz or 512Hz). + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateCalibrationOutPut(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + __HAL_RTC_CALIBRATION_OUTPUT_DISABLE(hrtc); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Enables the RTC reference clock detection. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_SetRefClock(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Enable the reference clock detection */ + __HAL_RTC_CLOCKREF_DETECTION_ENABLE(hrtc); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Disable the RTC reference clock detection. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DeactivateRefClock(RTC_HandleTypeDef *hrtc) +{ + HAL_StatusTypeDef status; + + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Enter Initialization mode */ + status = RTC_EnterInitMode(hrtc); + + if (status == HAL_OK) + { + /* Disable the reference clock detection */ + __HAL_RTC_CLOCKREF_DETECTION_DISABLE(hrtc); + + /* Exit Initialization mode */ + status = RTC_ExitInitMode(hrtc); + } + + if (status == HAL_OK) + { + hrtc->State = HAL_RTC_STATE_READY; + } + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return status; +} + +/** + * @brief Enables the Bypass Shadow feature. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_EnableBypassShadow(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set the BYPSHAD bit */ + hrtc->Instance->CR |= (uint8_t)RTC_CR_BYPSHAD; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @brief Disables the Bypass Shadow feature. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @note When the Bypass Shadow is enabled the calendar value are taken + * directly from the Calendar counter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_DisableBypassShadow(RTC_HandleTypeDef *hrtc) +{ + /* Process Locked */ + __HAL_LOCK(hrtc); + + hrtc->State = HAL_RTC_STATE_BUSY; + + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Reset the BYPSHAD bit */ + hrtc->Instance->CR &= (uint8_t)~RTC_CR_BYPSHAD; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hrtc); + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup RTCEx_Exported_Functions_Group4 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) RTC Alarm B callback + (+) RTC Poll for Alarm B request + +@endverbatim + * @{ + */ + +/** + * @brief Alarm B callback. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @retval None + */ +__weak void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hrtc); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_RTCEx_AlarmBEventCallback could be implemented in the user file + */ +} + +/** + * @brief Handles Alarm B Polling request. + * @param hrtc pointer to a RTC_HandleTypeDef structure that contains + * the configuration information for RTC. + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_RTCEx_PollForAlarmBEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait till RTC ALRBF flag is set and if timeout is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRBF) == 0U) + { + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hrtc->State = HAL_RTC_STATE_TIMEOUT; + return HAL_TIMEOUT; + } + } + } + + /* Clear the Alarm flag */ + __HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRBF); + + /* Change RTC state */ + hrtc->State = HAL_RTC_STATE_READY; + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_RTC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c new file mode 100644 index 0000000..eda41dd --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai.c @@ -0,0 +1,2554 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sai.c + * @author MCD Application Team + * @brief SAI HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Serial Audio Interface (SAI) peripheral: + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral Control functions + * + Peripheral State functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 SAI HAL driver can be used as follows: + + (#) Declare a SAI_HandleTypeDef handle structure (eg. SAI_HandleTypeDef hsai). + (#) Initialize the SAI low level resources by implementing the HAL_SAI_MspInit() API: + (##) Enable the SAI interface clock. + (##) SAI pins configuration: + (+++) Enable the clock for the SAI GPIOs. + (+++) Configure these SAI pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_SAI_Transmit_IT() + and HAL_SAI_Receive_IT() APIs): + (+++) Configure the SAI interrupt priority. + (+++) Enable the NVIC SAI IRQ handle. + + (##) DMA Configuration if you need to use DMA process (HAL_SAI_Transmit_DMA() + and HAL_SAI_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx Stream. + (+++) Associate the initialized DMA handle to the SAI DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the + DMA Tx/Rx Stream. + + (#) The initialization can be done by two ways + (##) Expert mode : Initialize the structures Init, FrameInit and SlotInit and call HAL_SAI_Init(). + (##) Simplified mode : Initialize the high part of Init Structure and call HAL_SAI_InitProtocol(). + + [..] + (@) The specific SAI interrupts (FIFO request and Overrun underrun interrupt) + will be managed using the macros __HAL_SAI_ENABLE_IT() and __HAL_SAI_DISABLE_IT() + inside the transmit and receive process. + + [..] + (@) SAI Clock Source configuration is managed differently depending on the selected + STM32F4 devices : + (+@) For STM32F446xx devices, the configuration is managed through RCCEx_PeriphCLKConfig() + function in the HAL RCC drivers + (+@) For STM32F439xx/STM32F437xx/STM32F429xx/STM32F427xx devices, the configuration + is managed within HAL SAI drivers through HAL_SAI_Init() function using + ClockSource field of SAI_InitTypeDef structure. + [..] + (@) Make sure that either: + (+@) I2S PLL is configured or + (+@) SAI PLL is configured or + (+@) External clock source is configured after setting correctly + the define constant EXTERNAL_CLOCK_VALUE in the stm32f4xx_hal_conf.h file. + [..] + (@) In master Tx mode: enabling the audio block immediately generates the bit clock + for the external slaves even if there is no data in the FIFO, However FS signal + generation is conditioned by the presence of data in the FIFO. + + [..] + (@) In master Rx mode: enabling the audio block immediately generates the bit clock + and FS signal for the external slaves. + + [..] + (@) It is mandatory to respect the following conditions in order to avoid bad SAI behavior: + (+@) First bit Offset <= (SLOT size - Data size) + (+@) Data size <= SLOT size + (+@) Number of SLOT x SLOT size = Frame length + (+@) The number of slots should be even when SAI_FS_CHANNEL_IDENTIFICATION is selected. + + [..] + Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_SAI_Transmit() + (+) Receive an amount of data in blocking mode using HAL_SAI_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non-blocking mode using HAL_SAI_Transmit_IT() + (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SAI_TxCpltCallback() + (+) Receive an amount of data in non-blocking mode using HAL_SAI_Receive_IT() + (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SAI_RxCpltCallback() + (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SAI_ErrorCallback() + + *** DMA mode IO operation *** + ============================= + [..] + (+) Send an amount of data in non-blocking mode (DMA) using HAL_SAI_Transmit_DMA() + (+) At transmission end of transfer HAL_SAI_TxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SAI_TxCpltCallback() + (+) Receive an amount of data in non-blocking mode (DMA) using HAL_SAI_Receive_DMA() + (+) At reception end of transfer HAL_SAI_RxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SAI_RxCpltCallback() + (+) In case of flag error, HAL_SAI_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SAI_ErrorCallback() + (+) Pause the DMA Transfer using HAL_SAI_DMAPause() + (+) Resume the DMA Transfer using HAL_SAI_DMAResume() + (+) Stop the DMA Transfer using HAL_SAI_DMAStop() + + *** SAI HAL driver additional function list *** + =============================================== + [..] + Below the list the others API available SAI HAL driver : + + (+) HAL_SAI_EnableTxMuteMode(): Enable the mute in tx mode + (+) HAL_SAI_DisableTxMuteMode(): Disable the mute in tx mode + (+) HAL_SAI_EnableRxMuteMode(): Enable the mute in Rx mode + (+) HAL_SAI_DisableRxMuteMode(): Disable the mute in Rx mode + (+) HAL_SAI_FlushRxFifo(): Flush the rx fifo. + (+) HAL_SAI_Abort(): Abort the current transfer + + *** SAI HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in SAI HAL driver : + + (+) __HAL_SAI_ENABLE(): Enable the SAI peripheral + (+) __HAL_SAI_DISABLE(): Disable the SAI peripheral + (+) __HAL_SAI_ENABLE_IT(): Enable the specified SAI interrupts + (+) __HAL_SAI_DISABLE_IT(): Disable the specified SAI interrupts + (+) __HAL_SAI_GET_IT_SOURCE(): Check if the specified SAI interrupt source is + enabled or disabled + (+) __HAL_SAI_GET_FLAG(): Check whether the specified SAI flag is set or not + + *** Callback registration *** + ============================= + [..] + The compilation define USE_HAL_SAI_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use functions HAL_SAI_RegisterCallback() to register a user callback. + + [..] + Function HAL_SAI_RegisterCallback() allows to register following callbacks: + (+) RxCpltCallback : SAI receive complete. + (+) RxHalfCpltCallback : SAI receive half complete. + (+) TxCpltCallback : SAI transmit complete. + (+) TxHalfCpltCallback : SAI transmit half complete. + (+) ErrorCallback : SAI error. + (+) MspInitCallback : SAI MspInit. + (+) MspDeInitCallback : SAI MspDeInit. + [..] + This function takes as parameters the HAL peripheral handle, the callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_SAI_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_SAI_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the callback ID. + [..] + This function allows to reset following callbacks: + (+) RxCpltCallback : SAI receive complete. + (+) RxHalfCpltCallback : SAI receive half complete. + (+) TxCpltCallback : SAI transmit complete. + (+) TxHalfCpltCallback : SAI transmit half complete. + (+) ErrorCallback : SAI error. + (+) MspInitCallback : SAI MspInit. + (+) MspDeInitCallback : SAI MspDeInit. + + [..] + By default, after the HAL_SAI_Init and if the state is HAL_SAI_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions: + examples HAL_SAI_RxCpltCallback(), HAL_SAI_ErrorCallback(). + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_SAI_Init + and HAL_SAI_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_SAI_Init and HAL_SAI_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_SAI_RegisterCallback before calling HAL_SAI_DeInit + or HAL_SAI_Init function. + + [..] + When the compilation define USE_HAL_SAI_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SAI SAI + * @brief SAI HAL module driver + * @{ + */ + +#ifdef HAL_SAI_MODULE_ENABLED + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) ||\ + defined(STM32F423xx) + +/** @defgroup SAI_Private_Typedefs SAI Private Typedefs + * @{ + */ +typedef enum +{ + SAI_MODE_DMA, + SAI_MODE_IT +} SAI_ModeTypedef; +/** + * @} + */ + +/* Private define ------------------------------------------------------------*/ + +/** @defgroup SAI_Private_Constants SAI Private Constants + * @{ + */ +#define SAI_DEFAULT_TIMEOUT 4U /* 4ms */ +#define SAI_LONG_TIMEOUT 1000U /* 1s */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup SAI_Private_Functions SAI Private Functions + * @{ + */ +static void SAI_FillFifo(SAI_HandleTypeDef *hsai); +static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode); +static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); +static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot); + +static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai); +static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai); +static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai); +static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai); +static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai); +static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai); +static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai); + +static void SAI_DMATxCplt(DMA_HandleTypeDef *hdma); +static void SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void SAI_DMARxCplt(DMA_HandleTypeDef *hdma); +static void SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void SAI_DMAError(DMA_HandleTypeDef *hdma); +static void SAI_DMAAbort(DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup SAI_Exported_Functions SAI Exported Functions + * @{ + */ + +/** @defgroup SAI_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + de-initialize the SAIx peripheral: + + (+) User must implement HAL_SAI_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_SAI_Init() to configure the selected device with + the selected configuration: + (++) Mode (Master/slave TX/RX) + (++) Protocol + (++) Data Size + (++) MCLK Output + (++) Audio frequency + (++) FIFO Threshold + (++) Frame Config + (++) Slot Config + + (+) Call the function HAL_SAI_DeInit() to restore the default configuration + of the selected SAI peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the structure FrameInit, SlotInit and the low part of + * Init according to the specified parameters and call the function + * HAL_SAI_Init to initialize the SAI block. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param protocol one of the supported protocol @ref SAI_Protocol + * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize + * the configuration information for SAI module. + * @param nbslot Number of slot. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_InitProtocol(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_SAI_SUPPORTED_PROTOCOL(protocol)); + assert_param(IS_SAI_PROTOCOL_DATASIZE(datasize)); + + switch (protocol) + { + case SAI_I2S_STANDARD : + case SAI_I2S_MSBJUSTIFIED : + case SAI_I2S_LSBJUSTIFIED : + status = SAI_InitI2S(hsai, protocol, datasize, nbslot); + break; + case SAI_PCM_LONG : + case SAI_PCM_SHORT : + status = SAI_InitPCM(hsai, protocol, datasize, nbslot); + break; + default : + status = HAL_ERROR; + break; + } + + if (status == HAL_OK) + { + status = HAL_SAI_Init(hsai); + } + + return status; +} + +/** + * @brief Initialize the SAI according to the specified parameters. + * in the SAI_InitTypeDef structure and initialize the associated handle. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Init(SAI_HandleTypeDef *hsai) +{ + uint32_t tmpregisterGCR = 0U; + + /* This variable used to store the SAI_CK_x (value in Hz) */ + uint32_t freq = 0U; + + /* This variable is used to compute CKSTR bits of SAI CR1 according to + ClockStrobing and AudioMode fields */ + uint32_t ckstr_bits = 0U; + uint32_t syncen_bits = 0U; + + /* Check the SAI handle allocation */ + if (hsai == NULL) + { + return HAL_ERROR; + } + + /* check the instance */ + assert_param(IS_SAI_ALL_INSTANCE(hsai->Instance)); + + /* Check the SAI Block parameters */ + assert_param(IS_SAI_AUDIO_FREQUENCY(hsai->Init.AudioFrequency)); + assert_param(IS_SAI_BLOCK_PROTOCOL(hsai->Init.Protocol)); + assert_param(IS_SAI_BLOCK_MODE(hsai->Init.AudioMode)); + assert_param(IS_SAI_BLOCK_SYNCEXT(hsai->Init.SynchroExt)); + assert_param(IS_SAI_BLOCK_DATASIZE(hsai->Init.DataSize)); + assert_param(IS_SAI_BLOCK_FIRST_BIT(hsai->Init.FirstBit)); + assert_param(IS_SAI_BLOCK_CLOCK_STROBING(hsai->Init.ClockStrobing)); + assert_param(IS_SAI_BLOCK_SYNCHRO(hsai->Init.Synchro)); + assert_param(IS_SAI_BLOCK_OUTPUT_DRIVE(hsai->Init.OutputDrive)); + assert_param(IS_SAI_BLOCK_NODIVIDER(hsai->Init.NoDivider)); + assert_param(IS_SAI_BLOCK_FIFO_THRESHOLD(hsai->Init.FIFOThreshold)); + assert_param(IS_SAI_MONO_STEREO_MODE(hsai->Init.MonoStereoMode)); + assert_param(IS_SAI_BLOCK_COMPANDING_MODE(hsai->Init.CompandingMode)); + assert_param(IS_SAI_BLOCK_TRISTATE_MANAGEMENT(hsai->Init.TriState)); + + /* Check the SAI Block Frame parameters */ + assert_param(IS_SAI_BLOCK_FRAME_LENGTH(hsai->FrameInit.FrameLength)); + assert_param(IS_SAI_BLOCK_ACTIVE_FRAME(hsai->FrameInit.ActiveFrameLength)); + assert_param(IS_SAI_BLOCK_FS_DEFINITION(hsai->FrameInit.FSDefinition)); + assert_param(IS_SAI_BLOCK_FS_POLARITY(hsai->FrameInit.FSPolarity)); + assert_param(IS_SAI_BLOCK_FS_OFFSET(hsai->FrameInit.FSOffset)); + + /* Check the SAI Block Slot parameters */ + assert_param(IS_SAI_BLOCK_FIRSTBIT_OFFSET(hsai->SlotInit.FirstBitOffset)); + assert_param(IS_SAI_BLOCK_SLOT_SIZE(hsai->SlotInit.SlotSize)); + assert_param(IS_SAI_BLOCK_SLOT_NUMBER(hsai->SlotInit.SlotNumber)); + assert_param(IS_SAI_SLOT_ACTIVE(hsai->SlotInit.SlotActive)); + + if (hsai->State == HAL_SAI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsai->Lock = HAL_UNLOCKED; + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + /* Reset callback pointers to the weak predefined callbacks */ + hsai->RxCpltCallback = HAL_SAI_RxCpltCallback; + hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback; + hsai->TxCpltCallback = HAL_SAI_TxCpltCallback; + hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback; + hsai->ErrorCallback = HAL_SAI_ErrorCallback; + + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + if (hsai->MspInitCallback == NULL) + { + hsai->MspInitCallback = HAL_SAI_MspInit; + } + hsai->MspInitCallback(hsai); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */ + HAL_SAI_MspInit(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + + hsai->State = HAL_SAI_STATE_BUSY; + + /* Disable the selected SAI peripheral */ + SAI_Disable(hsai); + + /* SAI Block Synchro Configuration -----------------------------------------*/ + SAI_BlockSynchroConfig(hsai); + + /* Configure Master Clock using the following formula : + MCLK_x = SAI_CK_x / (MCKDIV[3:0] * 2) with MCLK_x = 256 * FS + FS = SAI_CK_x / (MCKDIV[3:0] * 2) * 256 + MCKDIV[3:0] = SAI_CK_x / FS * 512 */ + if (hsai->Init.AudioFrequency != SAI_AUDIO_FREQUENCY_MCKDIV) + { + /* Get SAI clock source based on Source clock selection from RCC */ + freq = SAI_GetInputClock(hsai); + + /* (saiclocksource x 10) to keep Significant digits */ + tmpregisterGCR = (((freq * 10U) / ((hsai->Init.AudioFrequency) * 512U))); + + hsai->Init.Mckdiv = tmpregisterGCR / 10U; + + /* Round result to the nearest integer */ + if ((tmpregisterGCR % 10U) > 8U) + { + hsai->Init.Mckdiv += 1U; + } + + /* For SPDIF protocol, SAI shall provide a bit clock twice faster the symbol-rate */ + if (hsai->Init.Protocol == SAI_SPDIF_PROTOCOL) + { + hsai->Init.Mckdiv = hsai->Init.Mckdiv >> 1; + } + } + + /* Check the SAI Block master clock divider parameter */ + assert_param(IS_SAI_BLOCK_MASTER_DIVIDER(hsai->Init.Mckdiv)); + + /* Compute CKSTR bits of SAI CR1 according to ClockStrobing and AudioMode */ + if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) + { + ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? 0U : SAI_xCR1_CKSTR; + } + else + { + ckstr_bits = (hsai->Init.ClockStrobing == SAI_CLOCKSTROBING_RISINGEDGE) ? SAI_xCR1_CKSTR : 0U; + } + + /* SAI Block Configuration -------------------------------------------------*/ + switch (hsai->Init.Synchro) + { + case SAI_ASYNCHRONOUS : + { + syncen_bits = 0U; + } + break; + case SAI_SYNCHRONOUS : + { + syncen_bits = SAI_xCR1_SYNCEN_0; + } + break; + case SAI_SYNCHRONOUS_EXT_SAI1 : + case SAI_SYNCHRONOUS_EXT_SAI2 : + { + syncen_bits = SAI_xCR1_SYNCEN_1; + } + break; + default: + break; + } + + /* SAI CR1 Configuration */ + hsai->Instance->CR1 &= ~(SAI_xCR1_MODE | SAI_xCR1_PRTCFG | SAI_xCR1_DS | \ + SAI_xCR1_LSBFIRST | SAI_xCR1_CKSTR | SAI_xCR1_SYNCEN | \ + SAI_xCR1_MONO | SAI_xCR1_OUTDRIV | SAI_xCR1_DMAEN | \ + SAI_xCR1_NODIV | SAI_xCR1_MCKDIV); + + hsai->Instance->CR1 |= (hsai->Init.AudioMode | hsai->Init.Protocol | \ + hsai->Init.DataSize | hsai->Init.FirstBit | \ + ckstr_bits | syncen_bits | \ + hsai->Init.MonoStereoMode | hsai->Init.OutputDrive | \ + hsai->Init.NoDivider | (hsai->Init.Mckdiv << 20U)); + + /* SAI CR2 Configuration */ + hsai->Instance->CR2 &= ~(SAI_xCR2_FTH | SAI_xCR2_FFLUSH | SAI_xCR2_COMP | SAI_xCR2_CPL); + hsai->Instance->CR2 |= (hsai->Init.FIFOThreshold | hsai->Init.CompandingMode | hsai->Init.TriState); + + /* SAI Frame Configuration -----------------------------------------*/ + hsai->Instance->FRCR &= (~(SAI_xFRCR_FRL | SAI_xFRCR_FSALL | SAI_xFRCR_FSDEF | \ + SAI_xFRCR_FSPOL | SAI_xFRCR_FSOFF)); + hsai->Instance->FRCR |= ((hsai->FrameInit.FrameLength - 1U) | + hsai->FrameInit.FSOffset | + hsai->FrameInit.FSDefinition | + hsai->FrameInit.FSPolarity | + ((hsai->FrameInit.ActiveFrameLength - 1U) << 8U)); + + /* SAI Block_x SLOT Configuration ------------------------------------------*/ + /* This register has no meaning in AC 97 and SPDIF audio protocol */ + hsai->Instance->SLOTR &= ~(SAI_xSLOTR_FBOFF | SAI_xSLOTR_SLOTSZ | \ + SAI_xSLOTR_NBSLOT | SAI_xSLOTR_SLOTEN); + + hsai->Instance->SLOTR |= hsai->SlotInit.FirstBitOffset | hsai->SlotInit.SlotSize | \ + (hsai->SlotInit.SlotActive << 16U) | ((hsai->SlotInit.SlotNumber - 1U) << 8U); + + /* Initialize the error code */ + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + + /* Initialize the SAI state */ + hsai->State = HAL_SAI_STATE_READY; + + /* Release Lock */ + __HAL_UNLOCK(hsai); + + return HAL_OK; +} + +/** + * @brief DeInitialize the SAI peripheral. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DeInit(SAI_HandleTypeDef *hsai) +{ + /* Check the SAI handle allocation */ + if (hsai == NULL) + { + return HAL_ERROR; + } + + hsai->State = HAL_SAI_STATE_BUSY; + + /* Disabled All interrupt and clear all the flag */ + hsai->Instance->IMR = 0U; + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + /* Disable the SAI */ + SAI_Disable(hsai); + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC and DMA */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + if (hsai->MspDeInitCallback == NULL) + { + hsai->MspDeInitCallback = HAL_SAI_MspDeInit; + } + hsai->MspDeInitCallback(hsai); +#else + HAL_SAI_MspDeInit(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + + /* Initialize the error code */ + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + + /* Initialize the SAI state */ + hsai->State = HAL_SAI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hsai); + + return HAL_OK; +} + +/** + * @brief Initialize the SAI MSP. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the SAI MSP. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) +/** + * @brief Register a user SAI callback + * to be used instead of the weak predefined callback. + * @param hsai SAI handle. + * @param CallbackID ID of the callback to be registered. + * This parameter can be one of the following values: + * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID. + * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. + * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID. + * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. + * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID. + * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID. + * @param pCallback pointer to the callback function. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_SAI_RegisterCallback(SAI_HandleTypeDef *hsai, + HAL_SAI_CallbackIDTypeDef CallbackID, + pSAI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + else + { + if (HAL_SAI_STATE_READY == hsai->State) + { + switch (CallbackID) + { + case HAL_SAI_RX_COMPLETE_CB_ID : + hsai->RxCpltCallback = pCallback; + break; + case HAL_SAI_RX_HALFCOMPLETE_CB_ID : + hsai->RxHalfCpltCallback = pCallback; + break; + case HAL_SAI_TX_COMPLETE_CB_ID : + hsai->TxCpltCallback = pCallback; + break; + case HAL_SAI_TX_HALFCOMPLETE_CB_ID : + hsai->TxHalfCpltCallback = pCallback; + break; + case HAL_SAI_ERROR_CB_ID : + hsai->ErrorCallback = pCallback; + break; + case HAL_SAI_MSPINIT_CB_ID : + hsai->MspInitCallback = pCallback; + break; + case HAL_SAI_MSPDEINIT_CB_ID : + hsai->MspDeInitCallback = pCallback; + break; + default : + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SAI_STATE_RESET == hsai->State) + { + switch (CallbackID) + { + case HAL_SAI_MSPINIT_CB_ID : + hsai->MspInitCallback = pCallback; + break; + case HAL_SAI_MSPDEINIT_CB_ID : + hsai->MspDeInitCallback = pCallback; + break; + default : + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Unregister a user SAI callback. + * SAI callback is redirected to the weak predefined callback. + * @param hsai SAI handle. + * @param CallbackID ID of the callback to be unregistered. + * This parameter can be one of the following values: + * @arg @ref HAL_SAI_RX_COMPLETE_CB_ID receive complete callback ID. + * @arg @ref HAL_SAI_RX_HALFCOMPLETE_CB_ID receive half complete callback ID. + * @arg @ref HAL_SAI_TX_COMPLETE_CB_ID transmit complete callback ID. + * @arg @ref HAL_SAI_TX_HALFCOMPLETE_CB_ID transmit half complete callback ID. + * @arg @ref HAL_SAI_ERROR_CB_ID error callback ID. + * @arg @ref HAL_SAI_MSPINIT_CB_ID MSP init callback ID. + * @arg @ref HAL_SAI_MSPDEINIT_CB_ID MSP de-init callback ID. + * @retval HAL status. + */ +HAL_StatusTypeDef HAL_SAI_UnRegisterCallback(SAI_HandleTypeDef *hsai, + HAL_SAI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (HAL_SAI_STATE_READY == hsai->State) + { + switch (CallbackID) + { + case HAL_SAI_RX_COMPLETE_CB_ID : + hsai->RxCpltCallback = HAL_SAI_RxCpltCallback; + break; + case HAL_SAI_RX_HALFCOMPLETE_CB_ID : + hsai->RxHalfCpltCallback = HAL_SAI_RxHalfCpltCallback; + break; + case HAL_SAI_TX_COMPLETE_CB_ID : + hsai->TxCpltCallback = HAL_SAI_TxCpltCallback; + break; + case HAL_SAI_TX_HALFCOMPLETE_CB_ID : + hsai->TxHalfCpltCallback = HAL_SAI_TxHalfCpltCallback; + break; + case HAL_SAI_ERROR_CB_ID : + hsai->ErrorCallback = HAL_SAI_ErrorCallback; + break; + case HAL_SAI_MSPINIT_CB_ID : + hsai->MspInitCallback = HAL_SAI_MspInit; + break; + case HAL_SAI_MSPDEINIT_CB_ID : + hsai->MspDeInitCallback = HAL_SAI_MspDeInit; + break; + default : + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SAI_STATE_RESET == hsai->State) + { + switch (CallbackID) + { + case HAL_SAI_MSPINIT_CB_ID : + hsai->MspInitCallback = HAL_SAI_MspInit; + break; + case HAL_SAI_MSPDEINIT_CB_ID : + hsai->MspDeInitCallback = HAL_SAI_MspDeInit; + break; + default : + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update the error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + return status; +} +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SAI_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SAI data + transfers. + + (+) There are two modes of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated SAI IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (+) Blocking mode functions are : + (++) HAL_SAI_Transmit() + (++) HAL_SAI_Receive() + + (+) Non Blocking mode functions with Interrupt are : + (++) HAL_SAI_Transmit_IT() + (++) HAL_SAI_Receive_IT() + + (+) Non Blocking mode functions with DMA are : + (++) HAL_SAI_Transmit_DMA() + (++) HAL_SAI_Receive_DMA() + + (+) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_SAI_TxCpltCallback() + (++) HAL_SAI_RxCpltCallback() + (++) HAL_SAI_ErrorCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmit an amount of data in blocking mode. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Transmit(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->pBuffPtr = pData; + hsai->State = HAL_SAI_STATE_BUSY_TX; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* fill the fifo with data before to enabled the SAI */ + SAI_FillFifo(hsai); + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + while (hsai->XferCount > 0U) + { + /* Write data if the FIFO is not full */ + if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) + { + if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) + { + hsai->Instance->DR = (*hsai->pBuffPtr++); + } + else if (hsai->Init.DataSize <= SAI_DATASIZE_16) + { + hsai->Instance->DR = *((uint16_t *)hsai->pBuffPtr); + hsai->pBuffPtr += 2U; + } + else + { + hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); + hsai->pBuffPtr += 4U; + } + hsai->XferCount--; + } + else + { + /* Check for the Timeout */ + if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))) + { + /* Update error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; + + /* Clear all the flags */ + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + + /* Change the SAI state */ + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_ERROR; + } + } + } + + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in blocking mode. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Receive(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart = HAL_GetTick(); + + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->pBuffPtr = pData; + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->State = HAL_SAI_STATE_BUSY_RX; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + /* Receive data */ + while (hsai->XferCount > 0U) + { + if ((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_EMPTY) + { + if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) + { + (*hsai->pBuffPtr++) = hsai->Instance->DR; + } + else if (hsai->Init.DataSize <= SAI_DATASIZE_16) + { + *((uint16_t *)hsai->pBuffPtr) = hsai->Instance->DR; + hsai->pBuffPtr += 2U; + } + else + { + *((uint32_t *)hsai->pBuffPtr) = hsai->Instance->DR; + hsai->pBuffPtr += 4U; + } + hsai->XferCount--; + } + else + { + /* Check for the Timeout */ + if ((Timeout != HAL_MAX_DELAY) && ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))) + { + /* Update error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; + + /* Clear all the flags */ + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + + /* Change the SAI state */ + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_ERROR; + } + } + } + + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Transmit an amount of data in non-blocking mode with Interrupt. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) +{ + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->pBuffPtr = pData; + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + hsai->State = HAL_SAI_STATE_BUSY_TX; + + if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) + { + hsai->InterruptServiceRoutine = SAI_Transmit_IT8Bit; + } + else if (hsai->Init.DataSize <= SAI_DATASIZE_16) + { + hsai->InterruptServiceRoutine = SAI_Transmit_IT16Bit; + } + else + { + hsai->InterruptServiceRoutine = SAI_Transmit_IT32Bit; + } + + /* Fill the fifo before starting the communication */ + SAI_FillFifo(hsai); + + /* Enable FRQ and OVRUDR interrupts */ + __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in non-blocking mode with Interrupt. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Receive_IT(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) +{ + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->pBuffPtr = pData; + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + hsai->State = HAL_SAI_STATE_BUSY_RX; + + if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) + { + hsai->InterruptServiceRoutine = SAI_Receive_IT8Bit; + } + else if (hsai->Init.DataSize <= SAI_DATASIZE_16) + { + hsai->InterruptServiceRoutine = SAI_Receive_IT16Bit; + } + else + { + hsai->InterruptServiceRoutine = SAI_Receive_IT32Bit; + } + + /* Enable TXE and OVRUDR interrupts */ + __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pause the audio stream playing from the Media. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DMAPause(SAI_HandleTypeDef *hsai) +{ + /* Process Locked */ + __HAL_LOCK(hsai); + + /* Pause the audio file playing by disabling the SAI DMA requests */ + hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; +} + +/** + * @brief Resume the audio stream playing from the Media. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DMAResume(SAI_HandleTypeDef *hsai) +{ + /* Process Locked */ + __HAL_LOCK(hsai); + + /* Enable the SAI DMA requests */ + hsai->Instance->CR1 |= SAI_xCR1_DMAEN; + + /* If the SAI peripheral is still not enabled, enable it */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; +} + +/** + * @brief Stop the audio stream playing from the Media. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DMAStop(SAI_HandleTypeDef *hsai) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hsai); + + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Disable the SAI DMA request */ + hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; + + /* Abort the SAI Tx DMA Stream */ + if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX)) + { + if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) + { + /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */ + if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER) + { + status = HAL_ERROR; + hsai->ErrorCode |= HAL_SAI_ERROR_DMA; + } + } + } + + /* Abort the SAI Rx DMA Stream */ + if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX)) + { + if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) + { + /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */ + if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER) + { + status = HAL_ERROR; + hsai->ErrorCode |= HAL_SAI_ERROR_DMA; + } + } + } + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + + /* Set hsai state to ready */ + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return status; +} + +/** + * @brief Abort the current transfer and disable the SAI. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Abort(SAI_HandleTypeDef *hsai) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process Locked */ + __HAL_LOCK(hsai); + + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Check SAI DMA is enabled or not */ + if ((hsai->Instance->CR1 & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) + { + /* Disable the SAI DMA request */ + hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; + + /* Abort the SAI Tx DMA Stream */ + if ((hsai->hdmatx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_TX)) + { + if (HAL_DMA_Abort(hsai->hdmatx) != HAL_OK) + { + /* If the DMA Tx errorCode is different from DMA No Transfer then return Error */ + if (hsai->hdmatx->ErrorCode != HAL_DMA_ERROR_NO_XFER) + { + status = HAL_ERROR; + hsai->ErrorCode |= HAL_SAI_ERROR_DMA; + } + } + } + + /* Abort the SAI Rx DMA Stream */ + if ((hsai->hdmarx != NULL) && (hsai->State == HAL_SAI_STATE_BUSY_RX)) + { + if (HAL_DMA_Abort(hsai->hdmarx) != HAL_OK) + { + /* If the DMA Rx errorCode is different from DMA No Transfer then return Error */ + if (hsai->hdmarx->ErrorCode != HAL_DMA_ERROR_NO_XFER) + { + status = HAL_ERROR; + hsai->ErrorCode |= HAL_SAI_ERROR_DMA; + } + } + } + } + + /* Disabled All interrupt and clear all the flag */ + hsai->Instance->IMR = 0U; + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + + /* Set hsai state to ready */ + hsai->State = HAL_SAI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return status; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with DMA. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Transmit_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) +{ + uint32_t tickstart = HAL_GetTick(); + + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->pBuffPtr = pData; + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + hsai->State = HAL_SAI_STATE_BUSY_TX; + + /* Set the SAI Tx DMA Half transfer complete callback */ + hsai->hdmatx->XferHalfCpltCallback = SAI_DMATxHalfCplt; + + /* Set the SAI TxDMA transfer complete callback */ + hsai->hdmatx->XferCpltCallback = SAI_DMATxCplt; + + /* Set the DMA error callback */ + hsai->hdmatx->XferErrorCallback = SAI_DMAError; + + /* Set the DMA Tx abort callback */ + hsai->hdmatx->XferAbortCallback = NULL; + + /* Enable the Tx DMA Stream */ + if (HAL_DMA_Start_IT(hsai->hdmatx, (uint32_t)hsai->pBuffPtr, (uint32_t)&hsai->Instance->DR, hsai->XferSize) != HAL_OK) + { + __HAL_UNLOCK(hsai); + return HAL_ERROR; + } + + /* Enable the interrupts for error handling */ + __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); + + /* Enable SAI Tx DMA Request */ + hsai->Instance->CR1 |= SAI_xCR1_DMAEN; + + /* Wait until FIFO is not empty */ + while ((hsai->Instance->SR & SAI_xSR_FLVL) == SAI_FIFOSTATUS_EMPTY) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > SAI_LONG_TIMEOUT) + { + /* Update error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_TIMEOUT; + } + } + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == 0U) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) +{ + if ((pData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + if (hsai->State == HAL_SAI_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsai); + + hsai->pBuffPtr = pData; + hsai->XferSize = Size; + hsai->XferCount = Size; + hsai->ErrorCode = HAL_SAI_ERROR_NONE; + hsai->State = HAL_SAI_STATE_BUSY_RX; + + /* Set the SAI Rx DMA Half transfer complete callback */ + hsai->hdmarx->XferHalfCpltCallback = SAI_DMARxHalfCplt; + + /* Set the SAI Rx DMA transfer complete callback */ + hsai->hdmarx->XferCpltCallback = SAI_DMARxCplt; + + /* Set the DMA error callback */ + hsai->hdmarx->XferErrorCallback = SAI_DMAError; + + /* Set the DMA Rx abort callback */ + hsai->hdmarx->XferAbortCallback = NULL; + + /* Enable the Rx DMA Stream */ + if (HAL_DMA_Start_IT(hsai->hdmarx, (uint32_t)&hsai->Instance->DR, (uint32_t)hsai->pBuffPtr, hsai->XferSize) != HAL_OK) + { + __HAL_UNLOCK(hsai); + return HAL_ERROR; + } + + /* Enable the interrupts for error handling */ + __HAL_SAI_ENABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); + + /* Enable SAI Rx DMA Request */ + hsai->Instance->CR1 |= SAI_xCR1_DMAEN; + + /* Check if the SAI is already enabled */ + if ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) == RESET) + { + /* Enable SAI peripheral */ + __HAL_SAI_ENABLE(hsai); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hsai); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the Tx mute mode. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param val value sent during the mute @ref SAI_Block_Mute_Value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_EnableTxMuteMode(SAI_HandleTypeDef *hsai, uint16_t val) +{ + assert_param(IS_SAI_BLOCK_MUTE_VALUE(val)); + + if (hsai->State != HAL_SAI_STATE_RESET) + { + CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); + SET_BIT(hsai->Instance->CR2, SAI_xCR2_MUTE | val); + return HAL_OK; + } + return HAL_ERROR; +} + +/** + * @brief Disable the Tx mute mode. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DisableTxMuteMode(SAI_HandleTypeDef *hsai) +{ + if (hsai->State != HAL_SAI_STATE_RESET) + { + CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTEVAL | SAI_xCR2_MUTE); + return HAL_OK; + } + return HAL_ERROR; +} + +/** + * @brief Enable the Rx mute detection. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param callback function called when the mute is detected. + * @param counter number a data before mute detection max 63. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_EnableRxMuteMode(SAI_HandleTypeDef *hsai, SAIcallback callback, uint16_t counter) +{ + assert_param(IS_SAI_BLOCK_MUTE_COUNTER(counter)); + + if (hsai->State != HAL_SAI_STATE_RESET) + { + /* set the mute counter */ + CLEAR_BIT(hsai->Instance->CR2, SAI_xCR2_MUTECNT); + SET_BIT(hsai->Instance->CR2, (uint32_t)((uint32_t)counter << SAI_xCR2_MUTECNT_Pos)); + hsai->mutecallback = callback; + /* enable the IT interrupt */ + __HAL_SAI_ENABLE_IT(hsai, SAI_IT_MUTEDET); + return HAL_OK; + } + return HAL_ERROR; +} + +/** + * @brief Disable the Rx mute detection. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SAI_DisableRxMuteMode(SAI_HandleTypeDef *hsai) +{ + if (hsai->State != HAL_SAI_STATE_RESET) + { + /* set the mutecallback to NULL */ + hsai->mutecallback = (SAIcallback)NULL; + /* enable the IT interrupt */ + __HAL_SAI_DISABLE_IT(hsai, SAI_IT_MUTEDET); + return HAL_OK; + } + return HAL_ERROR; +} + +/** + * @brief Handle SAI interrupt request. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +void HAL_SAI_IRQHandler(SAI_HandleTypeDef *hsai) +{ + if (hsai->State != HAL_SAI_STATE_RESET) + { + uint32_t itflags = hsai->Instance->SR; + uint32_t itsources = hsai->Instance->IMR; + uint32_t cr1config = hsai->Instance->CR1; + uint32_t tmperror; + + /* SAI Fifo request interrupt occurred ------------------------------------*/ + if (((itflags & SAI_xSR_FREQ) == SAI_xSR_FREQ) && ((itsources & SAI_IT_FREQ) == SAI_IT_FREQ)) + { + hsai->InterruptServiceRoutine(hsai); + } + /* SAI Overrun error interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_OVRUDR) == SAI_FLAG_OVRUDR) && ((itsources & SAI_IT_OVRUDR) == SAI_IT_OVRUDR)) + { + /* Clear the SAI Overrun flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); + + /* Get the SAI error code */ + tmperror = ((hsai->State == HAL_SAI_STATE_BUSY_RX) ? HAL_SAI_ERROR_OVR : HAL_SAI_ERROR_UDR); + + /* Change the SAI error code */ + hsai->ErrorCode |= tmperror; + + /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + /* SAI mutedet interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_MUTEDET) == SAI_FLAG_MUTEDET) && ((itsources & SAI_IT_MUTEDET) == SAI_IT_MUTEDET)) + { + /* Clear the SAI mutedet flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_MUTEDET); + + /* call the call back function */ + if (hsai->mutecallback != (SAIcallback)NULL) + { + /* inform the user that an RX mute event has been detected */ + hsai->mutecallback(); + } + } + /* SAI AFSDET interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_AFSDET) == SAI_FLAG_AFSDET) && ((itsources & SAI_IT_AFSDET) == SAI_IT_AFSDET)) + { + /* Clear the SAI AFSDET flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_AFSDET); + + /* Change the SAI error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_AFSDET; + + /* Check SAI DMA is enabled or not */ + if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) + { + /* Abort the SAI DMA Streams */ + if (hsai->hdmatx != NULL) + { + /* Set the DMA Tx abort callback */ + hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmatx); + } + else if (hsai->hdmarx != NULL) + { + /* Set the DMA Rx abort callback */ + hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmarx); + } + } + else + { + /* Abort SAI */ + HAL_SAI_Abort(hsai); + + /* Set error callback */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + } + /* SAI LFSDET interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_LFSDET) == SAI_FLAG_LFSDET) && ((itsources & SAI_IT_LFSDET) == SAI_IT_LFSDET)) + { + /* Clear the SAI LFSDET flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_LFSDET); + + /* Change the SAI error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_LFSDET; + + /* Check SAI DMA is enabled or not */ + if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) + { + /* Abort the SAI DMA Streams */ + if (hsai->hdmatx != NULL) + { + /* Set the DMA Tx abort callback */ + hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmatx); + } + else if (hsai->hdmarx != NULL) + { + /* Set the DMA Rx abort callback */ + hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmarx); + } + } + else + { + /* Abort SAI */ + HAL_SAI_Abort(hsai); + + /* Set error callback */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + } + /* SAI WCKCFG interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_WCKCFG) == SAI_FLAG_WCKCFG) && ((itsources & SAI_IT_WCKCFG) == SAI_IT_WCKCFG)) + { + /* Clear the SAI WCKCFG flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_WCKCFG); + + /* Change the SAI error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_WCKCFG; + + /* Check SAI DMA is enabled or not */ + if ((cr1config & SAI_xCR1_DMAEN) == SAI_xCR1_DMAEN) + { + /* Abort the SAI DMA Streams */ + if (hsai->hdmatx != NULL) + { + /* Set the DMA Tx abort callback */ + hsai->hdmatx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmatx); + } + else if (hsai->hdmarx != NULL) + { + /* Set the DMA Rx abort callback */ + hsai->hdmarx->XferAbortCallback = SAI_DMAAbort; + + /* Abort DMA in IT mode */ + HAL_DMA_Abort_IT(hsai->hdmarx); + } + } + else + { + /* If WCKCFG occurs, SAI audio block is automatically disabled */ + /* Disable all interrupts and clear all flags */ + hsai->Instance->IMR = 0U; + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + /* Set the SAI state to ready to be able to start again the process */ + hsai->State = HAL_SAI_STATE_READY; + + /* Initialize XferCount */ + hsai->XferCount = 0U; + + /* SAI error Callback */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + } + /* SAI CNRDY interrupt occurred ----------------------------------*/ + else if (((itflags & SAI_FLAG_CNRDY) == SAI_FLAG_CNRDY) && ((itsources & SAI_IT_CNRDY) == SAI_IT_CNRDY)) + { + /* Clear the SAI CNRDY flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_CNRDY); + + /* Change the SAI error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_CNREADY; + + /* the transfer is not stopped, we will forward the information to the user and we let the user decide what needs to be done */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + else + { + /* Nothing to do */ + } + } +} + +/** + * @brief Tx Transfer completed callback. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Transfer Half completed callback. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer half completed callback. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief SAI error callback. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +__weak void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsai); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SAI_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup SAI_Exported_Functions_Group3 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the SAI handle state. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval HAL state + */ +HAL_SAI_StateTypeDef HAL_SAI_GetState(const SAI_HandleTypeDef *hsai) +{ + return hsai->State; +} + +/** + * @brief Return the SAI error code. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for the specified SAI Block. + * @retval SAI Error Code + */ +uint32_t HAL_SAI_GetError(const SAI_HandleTypeDef *hsai) +{ + return hsai->ErrorCode; +} +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SAI_Private_Functions + * @brief Private functions + * @{ + */ + +/** + * @brief Initialize the SAI I2S protocol according to the specified parameters + * in the SAI_InitTypeDef and create the associated handle. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param protocol one of the supported protocol. + * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize + * the configuration information for SAI module. + * @param nbslot number of slot minimum value is 2 and max is 16. + * the value must be a multiple of 2. + * @retval HAL status + */ +static HAL_StatusTypeDef SAI_InitI2S(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) +{ + hsai->Init.Protocol = SAI_FREE_PROTOCOL; + hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; + /* Compute ClockStrobing according AudioMode */ + if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) + { + /* Transmit */ + hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; + } + else + { + /* Receive */ + hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; + } + hsai->FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; + hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; + hsai->SlotInit.FirstBitOffset = 0U; + hsai->SlotInit.SlotNumber = nbslot; + + /* in IS2 the number of slot must be even */ + if ((nbslot & 0x1U) != 0U) + { + return HAL_ERROR; + } + + if (protocol == SAI_I2S_STANDARD) + { + hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; + hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; + } + else + { + /* SAI_I2S_MSBJUSTIFIED or SAI_I2S_LSBJUSTIFIED */ + hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; + hsai->FrameInit.FSOffset = SAI_FS_FIRSTBIT; + } + + /* Frame definition */ + switch (datasize) + { + case SAI_PROTOCOL_DATASIZE_16BIT: + hsai->Init.DataSize = SAI_DATASIZE_16; + hsai->FrameInit.FrameLength = 32U * (nbslot / 2U); + hsai->FrameInit.ActiveFrameLength = 16U * (nbslot / 2U); + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; + break; + case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : + hsai->Init.DataSize = SAI_DATASIZE_16; + hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); + hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + case SAI_PROTOCOL_DATASIZE_24BIT: + hsai->Init.DataSize = SAI_DATASIZE_24; + hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); + hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + case SAI_PROTOCOL_DATASIZE_32BIT: + hsai->Init.DataSize = SAI_DATASIZE_32; + hsai->FrameInit.FrameLength = 64U * (nbslot / 2U); + hsai->FrameInit.ActiveFrameLength = 32U * (nbslot / 2U); + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + default : + return HAL_ERROR; + } + if (protocol == SAI_I2S_LSBJUSTIFIED) + { + if (datasize == SAI_PROTOCOL_DATASIZE_16BITEXTENDED) + { + hsai->SlotInit.FirstBitOffset = 16U; + } + if (datasize == SAI_PROTOCOL_DATASIZE_24BIT) + { + hsai->SlotInit.FirstBitOffset = 8U; + } + } + return HAL_OK; +} + +/** + * @brief Initialize the SAI PCM protocol according to the specified parameters + * in the SAI_InitTypeDef and create the associated handle. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param protocol one of the supported protocol + * @param datasize one of the supported datasize @ref SAI_Protocol_DataSize + * @param nbslot number of slot minimum value is 1 and the max is 16. + * @retval HAL status + */ +static HAL_StatusTypeDef SAI_InitPCM(SAI_HandleTypeDef *hsai, uint32_t protocol, uint32_t datasize, uint32_t nbslot) +{ + hsai->Init.Protocol = SAI_FREE_PROTOCOL; + hsai->Init.FirstBit = SAI_FIRSTBIT_MSB; + /* Compute ClockStrobing according AudioMode */ + if ((hsai->Init.AudioMode == SAI_MODEMASTER_TX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) + { + /* Transmit */ + hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; + } + else + { + /* Receive */ + hsai->Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE; + } + hsai->FrameInit.FSDefinition = SAI_FS_STARTFRAME; + hsai->FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; + hsai->FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; + hsai->SlotInit.FirstBitOffset = 0U; + hsai->SlotInit.SlotNumber = nbslot; + hsai->SlotInit.SlotActive = SAI_SLOTACTIVE_ALL; + + if (protocol == SAI_PCM_SHORT) + { + hsai->FrameInit.ActiveFrameLength = 1; + } + else + { + /* SAI_PCM_LONG */ + hsai->FrameInit.ActiveFrameLength = 13; + } + + switch (datasize) + { + case SAI_PROTOCOL_DATASIZE_16BIT: + hsai->Init.DataSize = SAI_DATASIZE_16; + hsai->FrameInit.FrameLength = 16U * nbslot; + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_16B; + break; + case SAI_PROTOCOL_DATASIZE_16BITEXTENDED : + hsai->Init.DataSize = SAI_DATASIZE_16; + hsai->FrameInit.FrameLength = 32U * nbslot; + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + case SAI_PROTOCOL_DATASIZE_24BIT : + hsai->Init.DataSize = SAI_DATASIZE_24; + hsai->FrameInit.FrameLength = 32U * nbslot; + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + case SAI_PROTOCOL_DATASIZE_32BIT: + hsai->Init.DataSize = SAI_DATASIZE_32; + hsai->FrameInit.FrameLength = 32U * nbslot; + hsai->SlotInit.SlotSize = SAI_SLOTSIZE_32B; + break; + default : + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Fill the fifo. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_FillFifo(SAI_HandleTypeDef *hsai) +{ + /* fill the fifo with data before to enabled the SAI */ + while (((hsai->Instance->SR & SAI_xSR_FLVL) != SAI_FIFOSTATUS_FULL) && (hsai->XferCount > 0U)) + { + if ((hsai->Init.DataSize == SAI_DATASIZE_8) && (hsai->Init.CompandingMode == SAI_NOCOMPANDING)) + { + hsai->Instance->DR = (*hsai->pBuffPtr++); + } + else if (hsai->Init.DataSize <= SAI_DATASIZE_16) + { + hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); + hsai->pBuffPtr += 2U; + } + else + { + hsai->Instance->DR = *((uint32_t *)hsai->pBuffPtr); + hsai->pBuffPtr += 4U; + } + hsai->XferCount--; + } +} + +/** + * @brief Return the interrupt flag to set according the SAI setup. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @param mode SAI_MODE_DMA or SAI_MODE_IT + * @retval the list of the IT flag to enable + */ +static uint32_t SAI_InterruptFlag(const SAI_HandleTypeDef *hsai, uint32_t mode) +{ + uint32_t tmpIT = SAI_IT_OVRUDR; + + if (mode == SAI_MODE_IT) + { + tmpIT |= SAI_IT_FREQ; + } + + if ((hsai->Init.Protocol == SAI_AC97_PROTOCOL) && + ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODEMASTER_RX))) + { + tmpIT |= SAI_IT_CNRDY; + } + + if ((hsai->Init.AudioMode == SAI_MODESLAVE_RX) || (hsai->Init.AudioMode == SAI_MODESLAVE_TX)) + { + tmpIT |= SAI_IT_AFSDET | SAI_IT_LFSDET; + } + else + { + /* hsai has been configured in master mode */ + tmpIT |= SAI_IT_WCKCFG; + } + return tmpIT; +} + +/** + * @brief Disable the SAI and wait for the disabling. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai) +{ + uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U); + HAL_StatusTypeDef status = HAL_OK; + + /* Disable the SAI instance */ + __HAL_SAI_DISABLE(hsai); + + do + { + /* Check for the Timeout */ + if (count-- == 0U) + { + /* Update error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT; + status = HAL_TIMEOUT; + break; + } + } + while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != RESET); + + return status; +} + +/** + * @brief Tx Handler for Transmit in Interrupt mode 8-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Transmit_IT8Bit(SAI_HandleTypeDef *hsai) +{ + if (hsai->XferCount == 0U) + { + /* Handle the end of the transmission */ + /* Disable FREQ and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->TxCpltCallback(hsai); +#else + HAL_SAI_TxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + else + { + /* Write data on DR register */ + hsai->Instance->DR = (*hsai->pBuffPtr++); + hsai->XferCount--; + } +} + +/** + * @brief Tx Handler for Transmit in Interrupt mode for 16-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Transmit_IT16Bit(SAI_HandleTypeDef *hsai) +{ + if (hsai->XferCount == 0U) + { + /* Handle the end of the transmission */ + /* Disable FREQ and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->TxCpltCallback(hsai); +#else + HAL_SAI_TxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + else + { + /* Write data on DR register */ + hsai->Instance->DR = *(uint16_t *)hsai->pBuffPtr; + hsai->pBuffPtr += 2U; + hsai->XferCount--; + } +} + +/** + * @brief Tx Handler for Transmit in Interrupt mode for 32-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Transmit_IT32Bit(SAI_HandleTypeDef *hsai) +{ + if (hsai->XferCount == 0U) + { + /* Handle the end of the transmission */ + /* Disable FREQ and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->TxCpltCallback(hsai); +#else + HAL_SAI_TxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } + else + { + /* Write data on DR register */ + hsai->Instance->DR = *(uint32_t *)hsai->pBuffPtr; + hsai->pBuffPtr += 4U; + hsai->XferCount--; + } +} + +/** + * @brief Rx Handler for Receive in Interrupt mode 8-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Receive_IT8Bit(SAI_HandleTypeDef *hsai) +{ + /* Receive data */ + (*hsai->pBuffPtr++) = hsai->Instance->DR; + hsai->XferCount--; + + /* Check end of the transfer */ + if (hsai->XferCount == 0U) + { + /* Disable TXE and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + + /* Clear the SAI Overrun flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); + + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->RxCpltCallback(hsai); +#else + HAL_SAI_RxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Rx Handler for Receive in Interrupt mode for 16-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Receive_IT16Bit(SAI_HandleTypeDef *hsai) +{ + /* Receive data */ + *(uint16_t *)hsai->pBuffPtr = hsai->Instance->DR; + hsai->pBuffPtr += 2U; + hsai->XferCount--; + + /* Check end of the transfer */ + if (hsai->XferCount == 0U) + { + /* Disable TXE and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + + /* Clear the SAI Overrun flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); + + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->RxCpltCallback(hsai); +#else + HAL_SAI_RxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Rx Handler for Receive in Interrupt mode for 32-Bit transfer. + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval None + */ +static void SAI_Receive_IT32Bit(SAI_HandleTypeDef *hsai) +{ + /* Receive data */ + *(uint32_t *)hsai->pBuffPtr = hsai->Instance->DR; + hsai->pBuffPtr += 4U; + hsai->XferCount--; + + /* Check end of the transfer */ + if (hsai->XferCount == 0U) + { + /* Disable TXE and OVRUDR interrupts */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_IT)); + + /* Clear the SAI Overrun flag */ + __HAL_SAI_CLEAR_FLAG(hsai, SAI_FLAG_OVRUDR); + + hsai->State = HAL_SAI_STATE_READY; +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->RxCpltCallback(hsai); +#else + HAL_SAI_RxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief DMA SAI 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 SAI_DMATxCplt(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + if (hdma->Init.Mode != DMA_CIRCULAR) + { + hsai->XferCount = 0U; + + /* Disable SAI Tx DMA Request */ + hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); + + /* Stop the interrupts error handling */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); + + hsai->State = HAL_SAI_STATE_READY; + } +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->TxCpltCallback(hsai); +#else + HAL_SAI_TxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SAI 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 SAI_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->TxHalfCpltCallback(hsai); +#else + HAL_SAI_TxHalfCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SAI 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 SAI_DMARxCplt(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + if (hdma->Init.Mode != DMA_CIRCULAR) + { + /* Disable Rx DMA Request */ + hsai->Instance->CR1 &= (uint32_t)(~SAI_xCR1_DMAEN); + hsai->XferCount = 0U; + + /* Stop the interrupts error handling */ + __HAL_SAI_DISABLE_IT(hsai, SAI_InterruptFlag(hsai, SAI_MODE_DMA)); + + hsai->State = HAL_SAI_STATE_READY; + } +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->RxCpltCallback(hsai); +#else + HAL_SAI_RxCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SAI 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 SAI_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->RxHalfCpltCallback(hsai); +#else + HAL_SAI_RxHalfCpltCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SAI 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 SAI_DMAError(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Set SAI error code */ + hsai->ErrorCode |= HAL_SAI_ERROR_DMA; + + if ((hsai->hdmatx->ErrorCode == HAL_DMA_ERROR_TE) || (hsai->hdmarx->ErrorCode == HAL_DMA_ERROR_TE)) + { + /* Disable the SAI DMA request */ + hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; + + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Set the SAI state ready to be able to start again the process */ + hsai->State = HAL_SAI_STATE_READY; + + /* Initialize XferCount */ + hsai->XferCount = 0U; + } + /* SAI error Callback */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SAI Abort callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +static void SAI_DMAAbort(DMA_HandleTypeDef *hdma) +{ + SAI_HandleTypeDef *hsai = (SAI_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable DMA request */ + hsai->Instance->CR1 &= ~SAI_xCR1_DMAEN; + + /* Disable all interrupts and clear all flags */ + hsai->Instance->IMR = 0U; + hsai->Instance->CLRFR = 0xFFFFFFFFU; + + if (hsai->ErrorCode != HAL_SAI_ERROR_WCKCFG) + { + /* Disable SAI peripheral */ + SAI_Disable(hsai); + + /* Flush the fifo */ + SET_BIT(hsai->Instance->CR2, SAI_xCR2_FFLUSH); + } + /* Set the SAI state to ready to be able to start again the process */ + hsai->State = HAL_SAI_STATE_READY; + + /* Initialize XferCount */ + hsai->XferCount = 0U; + + /* SAI error Callback */ +#if (USE_HAL_SAI_REGISTER_CALLBACKS == 1) + hsai->ErrorCallback(hsai); +#else + HAL_SAI_ErrorCallback(hsai); +#endif /* USE_HAL_SAI_REGISTER_CALLBACKS */ +} + +/** + * @} + */ + +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ +#endif /* HAL_SAI_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c new file mode 100644 index 0000000..2d5e8c4 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sai_ex.c @@ -0,0 +1,310 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sai_ex.c + * @author MCD Application Team + * @brief SAI Extension HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of SAI extension peripheral: + * + Extension features functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 + ============================================================================== + ##### SAI peripheral extension features ##### + ============================================================================== + + [..] Comparing to other previous devices, the SAI interface for STM32F446xx + devices contains the following additional features : + + (+) Possibility to be clocked from PLLR + + ##### How to use this driver ##### + ============================================================================== + [..] This driver provides functions to manage several sources to clock SAI + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SAIEx SAIEx + * @brief SAI Extension HAL module driver + * @{ + */ + +#ifdef HAL_SAI_MODULE_ENABLED + +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || \ + defined(STM32F423xx) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* SAI registers Masks */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/** @defgroup SAI_Private_Functions SAI Private Functions + * @{ + */ +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SAIEx_Exported_Functions SAI Extended Exported Functions + * @{ + */ + +/** @defgroup SAIEx_Exported_Functions_Group1 Extension features functions + * @brief Extension features functions + * +@verbatim + =============================================================================== + ##### Extension features Functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the possible + SAI clock sources. + +@endverbatim + * @{ + */ + +/** + * @brief Configure SAI Block synchronization mode + * @param hsai pointer to a SAI_HandleTypeDef structure that contains + * the configuration information for SAI module. + * @retval SAI Clock Input + */ +void SAI_BlockSynchroConfig(const SAI_HandleTypeDef *hsai) +{ + uint32_t tmpregisterGCR; + +#if defined(STM32F446xx) + /* This setting must be done with both audio block (A & B) disabled */ + switch (hsai->Init.SynchroExt) + { + case SAI_SYNCEXT_DISABLE : + tmpregisterGCR = 0U; + break; + case SAI_SYNCEXT_OUTBLOCKA_ENABLE : + tmpregisterGCR = SAI_GCR_SYNCOUT_0; + break; + case SAI_SYNCEXT_OUTBLOCKB_ENABLE : + tmpregisterGCR = SAI_GCR_SYNCOUT_1; + break; + default: + tmpregisterGCR = 0U; + break; + } + + if ((hsai->Init.Synchro) == SAI_SYNCHRONOUS_EXT_SAI2) + { + tmpregisterGCR |= SAI_GCR_SYNCIN_0; + } + + if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) + { + SAI1->GCR = tmpregisterGCR; + } + else + { + SAI2->GCR = tmpregisterGCR; + } +#endif /* STM32F446xx */ +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) + /* This setting must be done with both audio block (A & B) disabled */ + switch (hsai->Init.SynchroExt) + { + case SAI_SYNCEXT_DISABLE : + tmpregisterGCR = 0U; + break; + case SAI_SYNCEXT_OUTBLOCKA_ENABLE : + tmpregisterGCR = SAI_GCR_SYNCOUT_0; + break; + case SAI_SYNCEXT_OUTBLOCKB_ENABLE : + tmpregisterGCR = SAI_GCR_SYNCOUT_1; + break; + default: + tmpregisterGCR = 0U; + break; + } + SAI1->GCR = tmpregisterGCR; +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ +} +/** +* @brief Get SAI Input Clock based on SAI source clock selection +* @param hsai pointer to a SAI_HandleTypeDef structure that contains +* the configuration information for SAI module. +* @retval SAI Clock Input +*/ +uint32_t SAI_GetInputClock(const SAI_HandleTypeDef *hsai) +{ + /* This variable used to store the SAI_CK_x (value in Hz) */ + uint32_t saiclocksource = 0U; + +#if defined(STM32F446xx) + if ((hsai->Instance == SAI1_Block_A) || (hsai->Instance == SAI1_Block_B)) + { + saiclocksource = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI1); + } + else /* SAI2_Block_A || SAI2_Block_B*/ + { + saiclocksource = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SAI2); + } +#endif /* STM32F446xx */ +#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \ + defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F413xx) || defined(STM32F423xx) + uint32_t vcoinput = 0U, tmpreg = 0U; + + /* Check the SAI Block parameters */ + assert_param(IS_SAI_CLK_SOURCE(hsai->Init.ClockSource)); + + /* SAI Block clock source selection */ + if (hsai->Instance == SAI1_Block_A) + { + __HAL_RCC_SAI_BLOCKACLKSOURCE_CONFIG(hsai->Init.ClockSource); + } + else + { + __HAL_RCC_SAI_BLOCKBCLKSOURCE_CONFIG((uint32_t)(hsai->Init.ClockSource << 2U)); + } + + /* VCO Input Clock value calculation */ + if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSI) + { + /* In Case the PLL Source is HSI (Internal Clock) */ + vcoinput = (HSI_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM)); + } + else + { + /* In Case the PLL Source is HSE (External Clock) */ + vcoinput = ((HSE_VALUE / (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM))); + } +#if defined(STM32F413xx) || defined(STM32F423xx) + /* SAI_CLK_x : SAI Block Clock configuration for different clock sources selected */ + if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLR) + { + /* Configure the PLLI2S division factor */ + /* PLL_VCO Input = PLL_SOURCE/PLLM */ + /* PLL_VCO Output = PLL_VCO Input * PLLN */ + /* SAI_CLK(first level) = PLL_VCO Output/PLLR */ + tmpreg = (RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 28U; + saiclocksource = (vcoinput * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6U)) / (tmpreg); + + /* SAI_CLK_x = SAI_CLK(first level)/PLLDIVR */ + tmpreg = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLDIVR) >> 8U) + 1U); + + saiclocksource = saiclocksource / (tmpreg); + + } + else if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLI2S) + { + /* Configure the PLLI2S division factor */ + /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ + /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ + /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SR */ + tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28U; + saiclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg); + + /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVR */ + tmpreg = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVR) + 1U); + saiclocksource = saiclocksource / (tmpreg); + } + else if (hsai->Init.ClockSource == SAI_CLKSOURCE_HS) + { + if ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLSOURCE_HSE) + { + /* Get the I2S source clock value */ + saiclocksource = (uint32_t)(HSE_VALUE); + } + else + { + /* Get the I2S source clock value */ + saiclocksource = (uint32_t)(HSI_VALUE); + } + } + else /* sConfig->ClockSource == SAI_CLKSource_Ext */ + { + saiclocksource = EXTERNAL_CLOCK_VALUE; + } +#else + /* SAI_CLK_x : SAI Block Clock configuration for different clock sources selected */ + if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLSAI) + { + /* Configure the PLLI2S division factor */ + /* PLLSAI_VCO Input = PLL_SOURCE/PLLM */ + /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN */ + /* SAI_CLK(first level) = PLLSAI_VCO Output/PLLSAIQ */ + tmpreg = (RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIQ) >> 24U; + saiclocksource = (vcoinput * ((RCC->PLLSAICFGR & RCC_PLLSAICFGR_PLLSAIN) >> 6U)) / (tmpreg); + + /* SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ */ + tmpreg = (((RCC->DCKCFGR & RCC_DCKCFGR_PLLSAIDIVQ) >> 8U) + 1U); + saiclocksource = saiclocksource / (tmpreg); + + } + else if (hsai->Init.ClockSource == SAI_CLKSOURCE_PLLI2S) + { + /* Configure the PLLI2S division factor */ + /* PLLI2S_VCO Input = PLL_SOURCE/PLLM */ + /* PLLI2S_VCO Output = PLLI2S_VCO Input * PLLI2SN */ + /* SAI_CLK(first level) = PLLI2S_VCO Output/PLLI2SQ */ + tmpreg = (RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SQ) >> 24U; + saiclocksource = (vcoinput * ((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6U)) / (tmpreg); + + /* SAI_CLK_x = SAI_CLK(first level)/PLLI2SDIVQ */ + tmpreg = ((RCC->DCKCFGR & RCC_DCKCFGR_PLLI2SDIVQ) + 1U); + saiclocksource = saiclocksource / (tmpreg); + } + else /* sConfig->ClockSource == SAI_CLKSource_Ext */ + { + /* Enable the External Clock selection */ + __HAL_RCC_I2S_CONFIG(RCC_I2SCLKSOURCE_EXT); + + saiclocksource = EXTERNAL_CLOCK_VALUE; + } +#endif /* STM32F413xx || STM32F423xx */ +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ + /* the return result is the value of SAI clock */ + return saiclocksource; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx || STM32F413xx || STM32F423xx */ +#endif /* HAL_SAI_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c new file mode 100644 index 0000000..f4145e9 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd.c @@ -0,0 +1,3277 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sd.c + * @author MCD Application Team + * @brief SD card HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Secure Digital (SD) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State 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 ##### + ============================================================================== + [..] + This driver implements a high level communication layer for read and write from/to + this memory. The needed STM32 hardware resources (SDIO and GPIO) are performed by + the user in HAL_SD_MspInit() function (MSP layer). + Basically, the MSP layer configuration should be the same as we provide in the + examples. + You can easily tailor this configuration according to hardware resources. + + [..] + This driver is a generic layered driver for SDIO memories which uses the HAL + SDIO driver functions to interface with SD and uSD cards devices. + It is used as follows: + + (#)Initialize the SDIO low level resources by implementing the HAL_SD_MspInit() API: + (##) Enable the SDIO interface clock using __HAL_RCC_SDIO_CLK_ENABLE(); + (##) SDIO pins configuration for SD card + (+++) Enable the clock for the SDIO GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE(); + (+++) Configure these SDIO pins as alternate function pull-up using HAL_GPIO_Init() + and according to your pin assignment; + (##) DMA configuration if you need to use DMA process (HAL_SD_ReadBlocks_DMA() + and HAL_SD_WriteBlocks_DMA() APIs). + (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE(); + (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled. + (##) NVIC configuration if you need to use interrupt process when using DMA transfer. + (+++) Configure the SDIO and DMA interrupt priorities using functions + HAL_NVIC_SetPriority(); DMA priority is superior to SDIO's priority + (+++) Enable the NVIC DMA and SDIO IRQs using function HAL_NVIC_EnableIRQ() + (+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT() + and __HAL_SD_DISABLE_IT() inside the communication process. + (+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT() + and __HAL_SD_CLEAR_IT() + (##) NVIC configuration if you need to use interrupt process (HAL_SD_ReadBlocks_IT() + and HAL_SD_WriteBlocks_IT() APIs). + (+++) Configure the SDIO interrupt priorities using function HAL_NVIC_SetPriority(); + (+++) Enable the NVIC SDIO IRQs using function HAL_NVIC_EnableIRQ() + (+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT() + and __HAL_SD_DISABLE_IT() inside the communication process. + (+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT() + and __HAL_SD_CLEAR_IT() + (#) At this stage, you can perform SD read/write/erase operations after SD card initialization + + + *** SD Card Initialization and configuration *** + ================================================ + [..] + To initialize the SD Card, use the HAL_SD_Init() function. It Initializes + SDIO Peripheral(STM32 side) and the SD Card, and put it into StandBy State (Ready for data transfer). + This function provide the following operations: + + (#) Apply the SD Card initialization process at 400KHz and check the SD Card + type (Standard Capacity or High Capacity). You can change or adapt this + frequency by adjusting the "ClockDiv" field. + The SD Card frequency (SDIO_CK) is computed as follows: + + SDIO_CK = SDIOCLK / (ClockDiv + 2) + + In initialization mode and according to the SD Card standard, + make sure that the SDIO_CK frequency doesn't exceed 400KHz. + + This phase of initialization is done through SDIO_Init() and + SDIO_PowerState_ON() SDIO low level APIs. + + (#) Initialize the SD card. The API used is HAL_SD_InitCard(). + This phase allows the card initialization and identification + and check the SD Card type (Standard Capacity or High Capacity) + The initialization flow is compatible with SD standard. + + This API (HAL_SD_InitCard()) could be used also to reinitialize the card in case + of plug-off plug-in. + + (#) Configure the SD Card Data transfer frequency. You can change or adapt this + frequency by adjusting the "ClockDiv" field. + In transfer mode and according to the SD Card standard, make sure that the + SDIO_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch. + To be able to use a frequency higher than 24MHz, you should use the SDIO + peripheral in bypass mode. Refer to the corresponding reference manual + for more details. + + (#) Select the corresponding SD Card according to the address read with the step 2. + + (#) Configure the SD Card in wide bus mode: 4-bits data. + + *** SD Card Read operation *** + ============================== + [..] + (+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + + (+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + You could also check the DMA transfer process through the SD Rx interrupt event. + + (+) You can read from SD card in Interrupt mode by using function HAL_SD_ReadBlocks_IT(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + You could also check the IT transfer process through the SD Rx interrupt event. + + *** SD Card Write operation *** + =============================== + [..] + (+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + + (+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + You could also check the DMA transfer process through the SD Tx interrupt event. + + (+) You can write to SD card in Interrupt mode by using function HAL_SD_WriteBlocks_IT(). + This function support only 512-bytes block length (the block size should be + chosen as 512 bytes). + You can choose either one block read operation or multiple block read operation + by adjusting the "NumberOfBlocks" parameter. + After this, you have to ensure that the transfer is done correctly. The check is done + through HAL_SD_GetCardState() function for SD card state. + You could also check the IT transfer process through the SD Tx interrupt event. + + *** SD card status *** + ====================== + [..] + (+) The SD Status contains status bits that are related to the SD Memory + Card proprietary features. To get SD card status use the HAL_SD_GetCardStatus(). + + *** SD card information *** + =========================== + [..] + (+) To get SD card information, you can use the function HAL_SD_GetCardInfo(). + It returns useful information about the SD card such as block size, card type, + block number ... + + *** SD card CSD register *** + ============================ + (+) The HAL_SD_GetCardCSD() API allows to get the parameters of the CSD register. + Some of the CSD parameters are useful for card initialization and identification. + + *** SD card CID register *** + ============================ + (+) The HAL_SD_GetCardCID() API allows to get the parameters of the CID register. + Some of the CSD parameters are useful for card initialization and identification. + + *** SD HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in SD HAL driver. + + (+) __HAL_SD_ENABLE : Enable the SD device + (+) __HAL_SD_DISABLE : Disable the SD device + (+) __HAL_SD_DMA_ENABLE: Enable the SDIO DMA transfer + (+) __HAL_SD_DMA_DISABLE: Disable the SDIO DMA transfer + (+) __HAL_SD_ENABLE_IT: Enable the SD device interrupt + (+) __HAL_SD_DISABLE_IT: Disable the SD device interrupt + (+) __HAL_SD_GET_FLAG:Check whether the specified SD flag is set or not + (+) __HAL_SD_CLEAR_FLAG: Clear the SD's pending flags + + (@) You can refer to the SD HAL driver header file for more useful macros + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_SD_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_SD_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) MspInitCallback : SD MspInit. + (+) MspDeInitCallback : SD MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_SD_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) TxCpltCallback : callback when a transmission transfer is completed. + (+) RxCpltCallback : callback when a reception transfer is completed. + (+) ErrorCallback : callback when error occurs. + (+) AbortCpltCallback : callback when abort is completed. + (+) MspInitCallback : SD MspInit. + (+) MspDeInitCallback : SD MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_SD_Init and if the state is HAL_SD_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_SD_Init + and HAL_SD_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_SD_Init and HAL_SD_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_SD_RegisterCallback before calling HAL_SD_DeInit + or HAL_SD_Init function. + + When The compilation define USE_HAL_SD_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(SDIO) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup SD + * @{ + */ + +#ifdef HAL_SD_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup SD_Private_Defines + * @{ + */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup SD_Private_Functions SD Private Functions + * @{ + */ +static uint32_t SD_InitCard(SD_HandleTypeDef *hsd); +static uint32_t SD_PowerON(SD_HandleTypeDef *hsd); +static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus); +static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus); +static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd); +static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd); +static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR); +static void SD_PowerOFF(SD_HandleTypeDef *hsd); +static void SD_Write_IT(SD_HandleTypeDef *hsd); +static void SD_Read_IT(SD_HandleTypeDef *hsd); +static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void SD_DMAError(DMA_HandleTypeDef *hdma); +static void SD_DMATxAbort(DMA_HandleTypeDef *hdma); +static void SD_DMARxAbort(DMA_HandleTypeDef *hdma); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SD_Exported_Functions + * @{ + */ + +/** @addtogroup SD_Exported_Functions_Group1 + * @brief Initialization and de-initialization functions + * +@verbatim + ============================================================================== + ##### Initialization and de-initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize the SD + card device to be ready for use. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the SD according to the specified parameters in the + SD_HandleTypeDef and create the associated handle. + * @param hsd: Pointer to the SD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd) +{ + /* Check the SD handle allocation */ + if(hsd == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance)); + assert_param(IS_SDIO_CLOCK_EDGE(hsd->Init.ClockEdge)); + assert_param(IS_SDIO_CLOCK_BYPASS(hsd->Init.ClockBypass)); + assert_param(IS_SDIO_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave)); + assert_param(IS_SDIO_BUS_WIDE(hsd->Init.BusWide)); + assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl)); + assert_param(IS_SDIO_CLKDIV(hsd->Init.ClockDiv)); + + if(hsd->State == HAL_SD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsd->Lock = HAL_UNLOCKED; +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + /* Reset Callback pointers in HAL_SD_STATE_RESET only */ + hsd->TxCpltCallback = HAL_SD_TxCpltCallback; + hsd->RxCpltCallback = HAL_SD_RxCpltCallback; + hsd->ErrorCallback = HAL_SD_ErrorCallback; + hsd->AbortCpltCallback = HAL_SD_AbortCallback; + + if(hsd->MspInitCallback == NULL) + { + hsd->MspInitCallback = HAL_SD_MspInit; + } + + /* Init the low level hardware */ + hsd->MspInitCallback(hsd); +#else + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_SD_MspInit(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize the Card parameters */ + if (HAL_SD_InitCard(hsd) != HAL_OK) + { + return HAL_ERROR; + } + + /* Initialize the error code */ + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + /* Initialize the SD operation */ + hsd->Context = SD_CONTEXT_NONE; + + /* Initialize the SD state */ + hsd->State = HAL_SD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Initializes the SD Card. + * @param hsd: Pointer to SD handle + * @note This function initializes the SD card. It could be used when a card + re-initialization is needed. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd) +{ + uint32_t errorstate; + HAL_StatusTypeDef status; + SD_InitTypeDef Init; + + /* Default SDIO peripheral configuration for SD card initialization */ + Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + Init.BusWide = SDIO_BUS_WIDE_1B; + Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + Init.ClockDiv = SDIO_INIT_CLK_DIV; + + /* Initialize SDIO peripheral interface with default configuration */ + status = SDIO_Init(hsd->Instance, Init); + if(status != HAL_OK) + { + return HAL_ERROR; + } + + /* Disable SDIO Clock */ + __HAL_SD_DISABLE(hsd); + + /* Set Power State to ON */ + (void)SDIO_PowerState_ON(hsd->Instance); + + /* Enable SDIO Clock */ + __HAL_SD_ENABLE(hsd); + + /* Required power up waiting time before starting the SD initialization sequence */ + HAL_Delay(2); + + /* Identify card operating voltage */ + errorstate = SD_PowerON(hsd); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->State = HAL_SD_STATE_READY; + hsd->ErrorCode |= errorstate; + return HAL_ERROR; + } + + /* Card initialization */ + errorstate = SD_InitCard(hsd); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->State = HAL_SD_STATE_READY; + hsd->ErrorCode |= errorstate; + return HAL_ERROR; + } + + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief De-Initializes the SD card. + * @param hsd: Pointer to SD handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd) +{ + /* Check the SD handle allocation */ + if(hsd == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance)); + + hsd->State = HAL_SD_STATE_BUSY; + + /* Set SD power state to off */ + SD_PowerOFF(hsd); + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + if(hsd->MspDeInitCallback == NULL) + { + hsd->MspDeInitCallback = HAL_SD_MspDeInit; + } + + /* DeInit the low level hardware */ + hsd->MspDeInitCallback(hsd); +#else + /* De-Initialize the MSP layer */ + HAL_SD_MspDeInit(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + + hsd->ErrorCode = HAL_SD_ERROR_NONE; + hsd->State = HAL_SD_STATE_RESET; + + return HAL_OK; +} + + +/** + * @brief Initializes the SD MSP. + * @param hsd: Pointer to SD handle + * @retval None + */ +__weak void HAL_SD_MspInit(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_MspInit could be implemented in the user file + */ +} + +/** + * @brief De-Initialize SD MSP. + * @param hsd: Pointer to SD handle + * @retval None + */ +__weak void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_MspDeInit could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @addtogroup SD_Exported_Functions_Group2 + * @brief Data transfer functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the data + transfer from/to SD card. + +@endverbatim + * @{ + */ + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed by polling mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @param hsd: Pointer to SD handle + * @param pData: pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of SD blocks to read + * @param Timeout: Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count, data, dataremaining; + uint32_t add = BlockAdd; + uint8_t *tempbuff = pData; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = NumberOfBlocks * BLOCKSIZE; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Read block(s) in polling mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK; + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK; + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + /* Poll on SDIO flags */ + dataremaining = config.DataLength; +#if defined(SDIO_STA_STBITERR) + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) +#else /* SDIO_STA_STBITERR not defined */ + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) +#endif /* SDIO_STA_STBITERR */ + { + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U)) + { + /* Read data from SDIO Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = SDIO_ReadFIFO(hsd->Instance); + *tempbuff = (uint8_t)(data & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 8U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 16U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 24U) & 0xFFU); + tempbuff++; + dataremaining--; + } + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT; + hsd->State= HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_TIMEOUT; + } + } + + /* Send stop transmission command in case of multiblock read */ + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U)) + { + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Send stop transmission command */ + errorstate = SDMMC_CmdStopTransfer(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + } + } + + /* Get error state */ + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else + { + /* Nothing to do */ + } + + /* Empty FIFO if there is still any data */ + while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U)) + { + data = SDIO_ReadFIFO(hsd->Instance); + *tempbuff = (uint8_t)(data & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 8U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 16U) & 0xFFU); + tempbuff++; + dataremaining--; + *tempbuff = (uint8_t)((data >> 24U) & 0xFFU); + tempbuff++; + dataremaining--; + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT; + hsd->State= HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + } + + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + hsd->State = HAL_SD_STATE_READY; + + return HAL_OK; + } + else + { + hsd->ErrorCode |= HAL_SD_ERROR_BUSY; + return HAL_ERROR; + } +} + +/** + * @brief Allows to write block(s) to a specified address in a card. The Data + * transfer is managed by polling mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @param hsd: Pointer to SD handle + * @param pData: pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of SD blocks to write + * @param Timeout: Specify timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count, data, dataremaining; + uint32_t add = BlockAdd; + uint8_t *tempbuff = pData; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = NumberOfBlocks * BLOCKSIZE; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK; + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK; + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + /* Write block(s) in polling mode */ + dataremaining = config.DataLength; +#if defined(SDIO_STA_STBITERR) + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) +#else /* SDIO_STA_STBITERR not defined */ + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) +#endif /* SDIO_STA_STBITERR */ + { + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U)) + { + /* Write data to SDIO Tx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = (uint32_t)(*tempbuff); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 8U); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 16U); + tempbuff++; + dataremaining--; + data |= ((uint32_t)(*tempbuff) << 24U); + tempbuff++; + dataremaining--; + (void)SDIO_WriteFIFO(hsd->Instance, &data); + } + } + + if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_TIMEOUT; + } + } + + /* Send stop transmission command in case of multiblock write */ + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U)) + { + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Send stop transmission command */ + errorstate = SDMMC_CmdStopTransfer(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + } + } + + /* Get error state */ + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR)) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else + { + /* Nothing to do */ + } + + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + hsd->State = HAL_SD_STATE_READY; + + return HAL_OK; + } + else + { + hsd->ErrorCode |= HAL_SD_ERROR_BUSY; + return HAL_ERROR; + } +} + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed in interrupt mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @note You could also check the IT transfer process through the SD Rx + * interrupt event. + * @param hsd: Pointer to SD handle + * @param pData: Pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of blocks to read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + hsd->pRxBuffPtr = pData; + hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks; + +#if defined(SDIO_STA_STBITERR) + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF)); +#endif /* SDIO_STA_STBITERR */ + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Read Blocks in IT mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_IT); + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_IT); + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Writes block(s) to a specified address in a card. The Data transfer + * is managed in interrupt mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @note You could also check the IT transfer process through the SD Tx + * interrupt event. + * @param hsd: Pointer to SD handle + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of blocks to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + hsd->pTxBuffPtr = pData; + hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks; + + /* Enable transfer interrupts */ +#if defined(SDIO_STA_STBITERR) + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE)); +#endif /* SDIO_STA_STBITERR */ + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK| SD_CONTEXT_IT); + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_IT); + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Reads block(s) from a specified address in a card. The Data transfer + * is managed by DMA mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @note You could also check the DMA transfer process through the SD Rx + * interrupt event. + * @param hsd: Pointer SD handle + * @param pData: Pointer to the buffer that will contain the received data + * @param BlockAdd: Block Address from where data is to be read + * @param NumberOfBlocks: Number of blocks to read. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + +#if defined(SDIO_STA_STBITERR) + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); +#endif /* SDIO_STA_STBITERR */ + + /* Set the DMA transfer complete callback */ + hsd->hdmarx->XferCpltCallback = SD_DMAReceiveCplt; + + /* Set the DMA error callback */ + hsd->hdmarx->XferErrorCallback = SD_DMAError; + + /* Set the DMA Abort callback */ + hsd->hdmarx->XferAbortCallback = NULL; + + /* Force DMA Direction */ + hsd->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY; + MODIFY_REG(hsd->hdmarx->Instance->CR, DMA_SxCR_DIR, hsd->hdmarx->Init.Direction); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hsd->hdmarx, (uint32_t)&hsd->Instance->FIFO, (uint32_t)pData, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK) + { + __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DMA; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + else + { + /* Enable SD DMA transfer */ + __HAL_SD_DMA_ENABLE(hsd); + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Read Blocks in DMA mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA); + + /* Read Multi Block command */ + errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA); + + /* Read Single Block command */ + errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + return HAL_OK; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Writes block(s) to a specified address in a card. The Data transfer + * is managed by DMA mode. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @note You could also check the DMA transfer process through the SD Tx + * interrupt event. + * @param hsd: Pointer to SD handle + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param BlockAdd: Block Address where data will be written + * @param NumberOfBlocks: Number of blocks to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t add = BlockAdd; + + if(NULL == pData) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Initialize data control register */ + hsd->Instance->DCTRL = 0U; + + /* Enable SD Error interrupts */ +#if defined(SDIO_STA_STBITERR) + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); +#endif /* SDIO_STA_STBITERR */ + + /* Set the DMA transfer complete callback */ + hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt; + + /* Set the DMA error callback */ + hsd->hdmatx->XferErrorCallback = SD_DMAError; + + /* Set the DMA Abort callback */ + hsd->hdmatx->XferAbortCallback = NULL; + + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + add *= 512U; + } + + /* Write Blocks in Polling mode */ + if(NumberOfBlocks > 1U) + { + hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA); + + /* Write Multi Block command */ + errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add); + } + else + { + hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA); + + /* Write Single Block command */ + errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add); + } + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + + /* Enable SDIO DMA transfer */ + __HAL_SD_DMA_ENABLE(hsd); + + /* Force DMA Direction */ + hsd->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH; + MODIFY_REG(hsd->hdmatx->Instance->CR, DMA_SxCR_DIR, hsd->hdmatx->Init.Direction); + + /* Enable the DMA Channel */ + if(HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK) + { +#if defined(SDIO_STA_STBITERR) + __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); +#endif /* SDIO_STA_STBITERR */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_DMA; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + return HAL_ERROR; + } + else + { + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = BLOCKSIZE * NumberOfBlocks; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + return HAL_OK; + } + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Erases the specified memory area of the given SD card. + * @note This API should be followed by a check on the card state through + * HAL_SD_GetCardState(). + * @param hsd: Pointer to SD handle + * @param BlockStartAdd: Start Block address + * @param BlockEndAdd: End Block address + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd) +{ + uint32_t errorstate; + uint32_t start_add = BlockStartAdd; + uint32_t end_add = BlockEndAdd; + + if(hsd->State == HAL_SD_STATE_READY) + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + + if(end_add < start_add) + { + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + return HAL_ERROR; + } + + if(end_add > (hsd->SdCard.LogBlockNbr)) + { + hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_BUSY; + + /* Check if the card command class supports erase command */ + if(((hsd->SdCard.Class) & SDIO_CCCC_ERASE) == 0U) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + /* Get start and end block for high capacity cards */ + if(hsd->SdCard.CardType != CARD_SDHC_SDXC) + { + start_add *= 512U; + end_add *= 512U; + } + + /* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */ + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Send CMD32 SD_ERASE_GRP_START with argument as addr */ + errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + /* Send CMD33 SD_ERASE_GRP_END with argument as addr */ + errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + } + + /* Send CMD38 ERASE */ + errorstate = SDMMC_CmdErase(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + hsd->State = HAL_SD_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief This function handles SD card interrupt request. + * @param hsd: Pointer to SD handle + * @retval None + */ +void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd) +{ + uint32_t errorstate; + uint32_t context = hsd->Context; + + /* Check for SDIO interrupt flags */ + if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & SD_CONTEXT_IT) != 0U)) + { + SD_Read_IT(hsd); + } + + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) != RESET) + { + __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DATAEND); + +#if defined(SDIO_STA_STBITERR) + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_TXFIFOHE |\ + SDIO_IT_RXFIFOHF | SDIO_IT_STBITERR); +#else /* SDIO_STA_STBITERR not defined */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_TXFIFOHE |\ + SDIO_IT_RXFIFOHF); +#endif /* SDIO_STA_STBITERR */ + + hsd->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN); + + if((context & SD_CONTEXT_IT) != 0U) + { + if(((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) + { + errorstate = SDMMC_CmdStopTransfer(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= errorstate; +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) + { +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->RxCpltCallback(hsd); +#else + HAL_SD_RxCpltCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + else + { +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->TxCpltCallback(hsd); +#else + HAL_SD_TxCpltCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + else if((context & SD_CONTEXT_DMA) != 0U) + { + if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U) + { + errorstate = SDMMC_CmdStopTransfer(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= errorstate; +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U)) + { + /* Disable the DMA transfer for transmit request by setting the DMAEN bit + in the SD DCTRL register */ + hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + hsd->State = HAL_SD_STATE_READY; + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->TxCpltCallback(hsd); +#else + HAL_SD_TxCpltCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + else + { + /* Nothing to do */ + } + } + + else if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & SD_CONTEXT_IT) != 0U)) + { + SD_Write_IT(hsd); + } + +#if defined(SDIO_STA_STBITERR) + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR | SDIO_FLAG_STBITERR) != RESET) +#else /* SDIO_STA_STBITERR not defined */ + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET) +#endif /* SDIO_STA_STBITERR */ + { + /* Set Error code */ + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL) != RESET) + { + hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL; + } + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) != RESET) + { + hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT; + } + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR) != RESET) + { + hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN; + } + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR) != RESET) + { + hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN; + } +#if defined(SDIO_STA_STBITERR) + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR) != RESET) + { + hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT; + } +#endif /* SDIO_STA_STBITERR */ + +#if defined(SDIO_STA_STBITERR) + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR); + + /* Disable all interrupts */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR); +#else /* SDIO_STA_STBITERR not defined */ + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + /* Disable all interrupts */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); +#endif /* SDIO_STA_STBITERR */ + + hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance); + + if((context & SD_CONTEXT_IT) != 0U) + { + /* Set the SD state to ready to be able to start again the process */ + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + else if((context & SD_CONTEXT_DMA) != 0U) + { + /* Abort the SD DMA channel */ + if(((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) + { + /* Set the DMA Tx abort callback */ + hsd->hdmatx->XferAbortCallback = SD_DMATxAbort; + /* Abort DMA in IT mode */ + if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK) + { + SD_DMATxAbort(hsd->hdmatx); + } + } + else if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) + { + /* Set the DMA Rx abort callback */ + hsd->hdmarx->XferAbortCallback = SD_DMARxAbort; + /* Abort DMA in IT mode */ + if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK) + { + SD_DMARxAbort(hsd->hdmarx); + } + } + else + { + hsd->ErrorCode = HAL_SD_ERROR_NONE; + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->AbortCpltCallback(hsd); +#else + HAL_SD_AbortCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + else + { + /* Nothing to do */ + } + } + else + { + /* Nothing to do */ + } +} + +/** + * @brief return the SD state + * @param hsd: Pointer to sd handle + * @retval HAL state + */ +HAL_SD_StateTypeDef HAL_SD_GetState(SD_HandleTypeDef *hsd) +{ + return hsd->State; +} + +/** +* @brief Return the SD error code +* @param hsd : Pointer to a SD_HandleTypeDef structure that contains + * the configuration information. +* @retval SD Error Code +*/ +uint32_t HAL_SD_GetError(SD_HandleTypeDef *hsd) +{ + return hsd->ErrorCode; +} + +/** + * @brief Tx Transfer completed callbacks + * @param hsd: Pointer to SD handle + * @retval None + */ +__weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_TxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks + * @param hsd: Pointer SD handle + * @retval None + */ +__weak void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_RxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief SD error callbacks + * @param hsd: Pointer SD handle + * @retval None + */ +__weak void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_ErrorCallback can be implemented in the user file + */ +} + +/** + * @brief SD Abort callbacks + * @param hsd: Pointer SD handle + * @retval None + */ +__weak void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsd); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SD_AbortCallback can be implemented in the user file + */ +} + +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User SD Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hsd : SD handle + * @param CallbackID : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID + * @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID + * @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID + * @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID + * @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID + * @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SD_RegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID, pSD_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if(pCallback == NULL) + { + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hsd); + + if(hsd->State == HAL_SD_STATE_READY) + { + switch (CallbackID) + { + case HAL_SD_TX_CPLT_CB_ID : + hsd->TxCpltCallback = pCallback; + break; + case HAL_SD_RX_CPLT_CB_ID : + hsd->RxCpltCallback = pCallback; + break; + case HAL_SD_ERROR_CB_ID : + hsd->ErrorCallback = pCallback; + break; + case HAL_SD_ABORT_CB_ID : + hsd->AbortCpltCallback = pCallback; + break; + case HAL_SD_MSP_INIT_CB_ID : + hsd->MspInitCallback = pCallback; + break; + case HAL_SD_MSP_DEINIT_CB_ID : + hsd->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hsd->State == HAL_SD_STATE_RESET) + { + switch (CallbackID) + { + case HAL_SD_MSP_INIT_CB_ID : + hsd->MspInitCallback = pCallback; + break; + case HAL_SD_MSP_DEINIT_CB_ID : + hsd->MspDeInitCallback = pCallback; + break; + default : + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsd); + return status; +} + +/** + * @brief Unregister a User SD Callback + * SD Callback is redirected to the weak (surcharged) predefined callback + * @param hsd : SD handle + * @param CallbackID : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID + * @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID + * @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID + * @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID + * @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID + * @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_SD_UnRegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hsd); + + if(hsd->State == HAL_SD_STATE_READY) + { + switch (CallbackID) + { + case HAL_SD_TX_CPLT_CB_ID : + hsd->TxCpltCallback = HAL_SD_TxCpltCallback; + break; + case HAL_SD_RX_CPLT_CB_ID : + hsd->RxCpltCallback = HAL_SD_RxCpltCallback; + break; + case HAL_SD_ERROR_CB_ID : + hsd->ErrorCallback = HAL_SD_ErrorCallback; + break; + case HAL_SD_ABORT_CB_ID : + hsd->AbortCpltCallback = HAL_SD_AbortCallback; + break; + case HAL_SD_MSP_INIT_CB_ID : + hsd->MspInitCallback = HAL_SD_MspInit; + break; + case HAL_SD_MSP_DEINIT_CB_ID : + hsd->MspDeInitCallback = HAL_SD_MspDeInit; + break; + default : + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hsd->State == HAL_SD_STATE_RESET) + { + switch (CallbackID) + { + case HAL_SD_MSP_INIT_CB_ID : + hsd->MspInitCallback = HAL_SD_MspInit; + break; + case HAL_SD_MSP_DEINIT_CB_ID : + hsd->MspDeInitCallback = HAL_SD_MspDeInit; + break; + default : + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK; + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsd); + return status; +} +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup SD_Exported_Functions_Group3 + * @brief management functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the SD card + operations and get the related information + +@endverbatim + * @{ + */ + +/** + * @brief Returns information the information of the card which are stored on + * the CID register. + * @param hsd: Pointer to SD handle + * @param pCID: Pointer to a HAL_SD_CardCIDTypeDef structure that + * contains all CID register parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID) +{ + pCID->ManufacturerID = (uint8_t)((hsd->CID[0] & 0xFF000000U) >> 24U); + + pCID->OEM_AppliID = (uint16_t)((hsd->CID[0] & 0x00FFFF00U) >> 8U); + + pCID->ProdName1 = (((hsd->CID[0] & 0x000000FFU) << 24U) | ((hsd->CID[1] & 0xFFFFFF00U) >> 8U)); + + pCID->ProdName2 = (uint8_t)(hsd->CID[1] & 0x000000FFU); + + pCID->ProdRev = (uint8_t)((hsd->CID[2] & 0xFF000000U) >> 24U); + + pCID->ProdSN = (((hsd->CID[2] & 0x00FFFFFFU) << 8U) | ((hsd->CID[3] & 0xFF000000U) >> 24U)); + + pCID->Reserved1 = (uint8_t)((hsd->CID[3] & 0x00F00000U) >> 20U); + + pCID->ManufactDate = (uint16_t)((hsd->CID[3] & 0x000FFF00U) >> 8U); + + pCID->CID_CRC = (uint8_t)((hsd->CID[3] & 0x000000FEU) >> 1U); + + pCID->Reserved2 = 1U; + + return HAL_OK; +} + +/** + * @brief Returns information the information of the card which are stored on + * the CSD register. + * @param hsd: Pointer to SD handle + * @param pCSD: Pointer to a HAL_SD_CardCSDTypeDef structure that + * contains all CSD register parameters + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD) +{ + pCSD->CSDStruct = (uint8_t)((hsd->CSD[0] & 0xC0000000U) >> 30U); + + pCSD->SysSpecVersion = (uint8_t)((hsd->CSD[0] & 0x3C000000U) >> 26U); + + pCSD->Reserved1 = (uint8_t)((hsd->CSD[0] & 0x03000000U) >> 24U); + + pCSD->TAAC = (uint8_t)((hsd->CSD[0] & 0x00FF0000U) >> 16U); + + pCSD->NSAC = (uint8_t)((hsd->CSD[0] & 0x0000FF00U) >> 8U); + + pCSD->MaxBusClkFrec = (uint8_t)(hsd->CSD[0] & 0x000000FFU); + + pCSD->CardComdClasses = (uint16_t)((hsd->CSD[1] & 0xFFF00000U) >> 20U); + + pCSD->RdBlockLen = (uint8_t)((hsd->CSD[1] & 0x000F0000U) >> 16U); + + pCSD->PartBlockRead = (uint8_t)((hsd->CSD[1] & 0x00008000U) >> 15U); + + pCSD->WrBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00004000U) >> 14U); + + pCSD->RdBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00002000U) >> 13U); + + pCSD->DSRImpl = (uint8_t)((hsd->CSD[1] & 0x00001000U) >> 12U); + + pCSD->Reserved2 = 0U; /*!< Reserved */ + + if(hsd->SdCard.CardType == CARD_SDSC) + { + pCSD->DeviceSize = (((hsd->CSD[1] & 0x000003FFU) << 2U) | ((hsd->CSD[2] & 0xC0000000U) >> 30U)); + + pCSD->MaxRdCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x38000000U) >> 27U); + + pCSD->MaxRdCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x07000000U) >> 24U); + + pCSD->MaxWrCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x00E00000U) >> 21U); + + pCSD->MaxWrCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x001C0000U) >> 18U); + + pCSD->DeviceSizeMul = (uint8_t)((hsd->CSD[2] & 0x00038000U) >> 15U); + + hsd->SdCard.BlockNbr = (pCSD->DeviceSize + 1U) ; + hsd->SdCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U)); + hsd->SdCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU)); + + hsd->SdCard.LogBlockNbr = (hsd->SdCard.BlockNbr) * ((hsd->SdCard.BlockSize) / 512U); + hsd->SdCard.LogBlockSize = 512U; + } + else if(hsd->SdCard.CardType == CARD_SDHC_SDXC) + { + /* Byte 7 */ + pCSD->DeviceSize = (((hsd->CSD[1] & 0x0000003FU) << 16U) | ((hsd->CSD[2] & 0xFFFF0000U) >> 16U)); + + hsd->SdCard.BlockNbr = ((pCSD->DeviceSize + 1U) * 1024U); + hsd->SdCard.LogBlockNbr = hsd->SdCard.BlockNbr; + hsd->SdCard.BlockSize = 512U; + hsd->SdCard.LogBlockSize = hsd->SdCard.BlockSize; + } + else + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE; + hsd->State = HAL_SD_STATE_READY; + return HAL_ERROR; + } + + pCSD->EraseGrSize = (uint8_t)((hsd->CSD[2] & 0x00004000U) >> 14U); + + pCSD->EraseGrMul = (uint8_t)((hsd->CSD[2] & 0x00003F80U) >> 7U); + + pCSD->WrProtectGrSize = (uint8_t)(hsd->CSD[2] & 0x0000007FU); + + pCSD->WrProtectGrEnable = (uint8_t)((hsd->CSD[3] & 0x80000000U) >> 31U); + + pCSD->ManDeflECC = (uint8_t)((hsd->CSD[3] & 0x60000000U) >> 29U); + + pCSD->WrSpeedFact = (uint8_t)((hsd->CSD[3] & 0x1C000000U) >> 26U); + + pCSD->MaxWrBlockLen= (uint8_t)((hsd->CSD[3] & 0x03C00000U) >> 22U); + + pCSD->WriteBlockPaPartial = (uint8_t)((hsd->CSD[3] & 0x00200000U) >> 21U); + + pCSD->Reserved3 = 0; + + pCSD->ContentProtectAppli = (uint8_t)((hsd->CSD[3] & 0x00010000U) >> 16U); + + pCSD->FileFormatGroup = (uint8_t)((hsd->CSD[3] & 0x00008000U) >> 15U); + + pCSD->CopyFlag = (uint8_t)((hsd->CSD[3] & 0x00004000U) >> 14U); + + pCSD->PermWrProtect = (uint8_t)((hsd->CSD[3] & 0x00002000U) >> 13U); + + pCSD->TempWrProtect = (uint8_t)((hsd->CSD[3] & 0x00001000U) >> 12U); + + pCSD->FileFormat = (uint8_t)((hsd->CSD[3] & 0x00000C00U) >> 10U); + + pCSD->ECC= (uint8_t)((hsd->CSD[3] & 0x00000300U) >> 8U); + + pCSD->CSD_CRC = (uint8_t)((hsd->CSD[3] & 0x000000FEU) >> 1U); + + pCSD->Reserved4 = 1; + + return HAL_OK; +} + +/** + * @brief Gets the SD status info. + * @param hsd: Pointer to SD handle + * @param pStatus: Pointer to the HAL_SD_CardStatusTypeDef structure that + * will contain the SD card status information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus) +{ + uint32_t sd_status[16]; + uint32_t errorstate; + HAL_StatusTypeDef status = HAL_OK; + + errorstate = SD_SendSDStatus(hsd, sd_status); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + hsd->State = HAL_SD_STATE_READY; + status = HAL_ERROR; + } + else + { + pStatus->DataBusWidth = (uint8_t)((sd_status[0] & 0xC0U) >> 6U); + + pStatus->SecuredMode = (uint8_t)((sd_status[0] & 0x20U) >> 5U); + + pStatus->CardType = (uint16_t)(((sd_status[0] & 0x00FF0000U) >> 8U) | ((sd_status[0] & 0xFF000000U) >> 24U)); + + pStatus->ProtectedAreaSize = (((sd_status[1] & 0xFFU) << 24U) | ((sd_status[1] & 0xFF00U) << 8U) | + ((sd_status[1] & 0xFF0000U) >> 8U) | ((sd_status[1] & 0xFF000000U) >> 24U)); + + pStatus->SpeedClass = (uint8_t)(sd_status[2] & 0xFFU); + + pStatus->PerformanceMove = (uint8_t)((sd_status[2] & 0xFF00U) >> 8U); + + pStatus->AllocationUnitSize = (uint8_t)((sd_status[2] & 0xF00000U) >> 20U); + + pStatus->EraseSize = (uint16_t)(((sd_status[2] & 0xFF000000U) >> 16U) | (sd_status[3] & 0xFFU)); + + pStatus->EraseTimeout = (uint8_t)((sd_status[3] & 0xFC00U) >> 10U); + + pStatus->EraseOffset = (uint8_t)((sd_status[3] & 0x0300U) >> 8U); + } + + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode = errorstate; + hsd->State = HAL_SD_STATE_READY; + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Gets the SD card info. + * @param hsd: Pointer to SD handle + * @param pCardInfo: Pointer to the HAL_SD_CardInfoTypeDef structure that + * will contain the SD card status information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo) +{ + pCardInfo->CardType = (uint32_t)(hsd->SdCard.CardType); + pCardInfo->CardVersion = (uint32_t)(hsd->SdCard.CardVersion); + pCardInfo->Class = (uint32_t)(hsd->SdCard.Class); + pCardInfo->RelCardAdd = (uint32_t)(hsd->SdCard.RelCardAdd); + pCardInfo->BlockNbr = (uint32_t)(hsd->SdCard.BlockNbr); + pCardInfo->BlockSize = (uint32_t)(hsd->SdCard.BlockSize); + pCardInfo->LogBlockNbr = (uint32_t)(hsd->SdCard.LogBlockNbr); + pCardInfo->LogBlockSize = (uint32_t)(hsd->SdCard.LogBlockSize); + + return HAL_OK; +} + +/** + * @brief Enables wide bus operation for the requested card if supported by + * card. + * @param hsd: Pointer to SD handle + * @param WideMode: Specifies the SD card wide bus mode + * This parameter can be one of the following values: + * @arg SDIO_BUS_WIDE_8B: 8-bit data transfer + * @arg SDIO_BUS_WIDE_4B: 4-bit data transfer + * @arg SDIO_BUS_WIDE_1B: 1-bit data transfer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode) +{ + SDIO_InitTypeDef Init; + uint32_t errorstate; + HAL_StatusTypeDef status = HAL_OK; + + /* Check the parameters */ + assert_param(IS_SDIO_BUS_WIDE(WideMode)); + + /* Change State */ + hsd->State = HAL_SD_STATE_BUSY; + + if(hsd->SdCard.CardType != CARD_SECURED) + { + if(WideMode == SDIO_BUS_WIDE_8B) + { + hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE; + } + else if(WideMode == SDIO_BUS_WIDE_4B) + { + errorstate = SD_WideBus_Enable(hsd); + + hsd->ErrorCode |= errorstate; + } + else if(WideMode == SDIO_BUS_WIDE_1B) + { + errorstate = SD_WideBus_Disable(hsd); + + hsd->ErrorCode |= errorstate; + } + else + { + /* WideMode is not a valid argument*/ + hsd->ErrorCode |= HAL_SD_ERROR_PARAM; + } + } + else + { + /* MMC Card does not support this feature */ + hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE; + } + + if(hsd->ErrorCode != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->State = HAL_SD_STATE_READY; + status = HAL_ERROR; + } + else + { + /* Configure the SDIO peripheral */ + Init.ClockEdge = hsd->Init.ClockEdge; + Init.ClockBypass = hsd->Init.ClockBypass; + Init.ClockPowerSave = hsd->Init.ClockPowerSave; + Init.BusWide = WideMode; + Init.HardwareFlowControl = hsd->Init.HardwareFlowControl; + Init.ClockDiv = hsd->Init.ClockDiv; + (void)SDIO_Init(hsd->Instance, Init); + } + + /* Set Block Size for Card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE); + if(errorstate != HAL_SD_ERROR_NONE) + { + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + hsd->ErrorCode |= errorstate; + status = HAL_ERROR; + } + + /* Change State */ + hsd->State = HAL_SD_STATE_READY; + + return status; +} + +/** + * @brief Gets the current sd card data state. + * @param hsd: pointer to SD handle + * @retval Card state + */ +HAL_SD_CardStateTypeDef HAL_SD_GetCardState(SD_HandleTypeDef *hsd) +{ + uint32_t cardstate; + uint32_t errorstate; + uint32_t resp1 = 0; + + errorstate = SD_SendStatus(hsd, &resp1); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= errorstate; + } + + cardstate = ((resp1 >> 9U) & 0x0FU); + + return (HAL_SD_CardStateTypeDef)cardstate; +} + +/** + * @brief Abort the current transfer and disable the SD. + * @param hsd: pointer to a SD_HandleTypeDef structure that contains + * the configuration information for SD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd) +{ + HAL_SD_CardStateTypeDef CardState; + uint32_t context = hsd->Context; + + /* DIsable All interrupts */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN); + + if ((context & SD_CONTEXT_DMA) != 0U) + { + /* Disable the SD DMA request */ + hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Abort the SD DMA Tx channel */ + if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) + { + if(HAL_DMA_Abort(hsd->hdmatx) != HAL_OK) + { + hsd->ErrorCode |= HAL_SD_ERROR_DMA; + } + } + /* Abort the SD DMA Rx channel */ + else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) + { + if(HAL_DMA_Abort(hsd->hdmarx) != HAL_OK) + { + hsd->ErrorCode |= HAL_SD_ERROR_DMA; + } + } + else + { + /* Nothing to do */ + } + } + + hsd->State = HAL_SD_STATE_READY; + + /* Initialize the SD operation */ + hsd->Context = SD_CONTEXT_NONE; + + CardState = HAL_SD_GetCardState(hsd); + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + { + hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance); + } + if(hsd->ErrorCode != HAL_SD_ERROR_NONE) + { + return HAL_ERROR; + } + return HAL_OK; +} + +/** + * @brief Abort the current transfer and disable the SD (IT mode). + * @param hsd: pointer to a SD_HandleTypeDef structure that contains + * the configuration information for SD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd) +{ + HAL_SD_CardStateTypeDef CardState; + uint32_t context = hsd->Context; + + /* Disable All interrupts */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN); + + if ((context & SD_CONTEXT_DMA) != 0U) + { + /* Disable the SD DMA request */ + hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Abort the SD DMA Tx channel */ + if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) + { + hsd->hdmatx->XferAbortCallback = SD_DMATxAbort; + if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK) + { + hsd->hdmatx = NULL; + } + } + /* Abort the SD DMA Rx channel */ + else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) + { + hsd->hdmarx->XferAbortCallback = SD_DMARxAbort; + if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK) + { + hsd->hdmarx = NULL; + } + } + else + { + /* Nothing to do */ + } + } + /* No transfer ongoing on both DMA channels*/ + else + { + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + CardState = HAL_SD_GetCardState(hsd); + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + { + hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance); + } + if(hsd->ErrorCode != HAL_SD_ERROR_NONE) + { + return HAL_ERROR; + } + else + { +#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U) + hsd->AbortCpltCallback(hsd); +#else + HAL_SD_AbortCallback(hsd); +#endif /* USE_HAL_SD_REGISTER_CALLBACKS */ + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ + +/* Private function ----------------------------------------------------------*/ +/** @addtogroup SD_Private_Functions + * @{ + */ + +/** + * @brief DMA SD transmit process complete callback + * @param hdma: DMA handle + * @retval None + */ +static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + + /* Enable DATAEND Interrupt */ + __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND)); +} + +/** + * @brief DMA SD receive process complete callback + * @param hdma: DMA handle + * @retval None + */ +static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + uint32_t errorstate; + + /* Send stop command in multiblock write */ + if(hsd->Context == (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA)) + { + errorstate = SDMMC_CmdStopTransfer(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= errorstate; +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif + } + } + + /* Disable the DMA transfer for transmit request by setting the DMAEN bit + in the SD DCTRL register */ + hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN); + + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->RxCpltCallback(hsd); +#else + HAL_SD_RxCpltCallback(hsd); +#endif +} + +/** + * @brief DMA SD communication error callback + * @param hdma: DMA handle + * @retval None + */ +static void SD_DMAError(DMA_HandleTypeDef *hdma) +{ + SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + HAL_SD_CardStateTypeDef CardState; + uint32_t RxErrorCode, TxErrorCode; + + /* if DMA error is FIFO error ignore it */ + if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) + { + RxErrorCode = hsd->hdmarx->ErrorCode; + TxErrorCode = hsd->hdmatx->ErrorCode; + if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE)) + { + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS); + + /* Disable All interrupts */ + __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ + SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); + + hsd->ErrorCode |= HAL_SD_ERROR_DMA; + CardState = HAL_SD_GetCardState(hsd); + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + { + hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance); + } + + hsd->State= HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + } + +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif + } +} + +/** + * @brief DMA SD Tx Abort callback + * @param hdma: DMA handle + * @retval None + */ +static void SD_DMATxAbort(DMA_HandleTypeDef *hdma) +{ + SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + HAL_SD_CardStateTypeDef CardState; + + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + CardState = HAL_SD_GetCardState(hsd); + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + { + hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance); + } + + if(hsd->ErrorCode == HAL_SD_ERROR_NONE) + { +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->AbortCpltCallback(hsd); +#else + HAL_SD_AbortCallback(hsd); +#endif + } + else + { +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif + } +} + +/** + * @brief DMA SD Rx Abort callback + * @param hdma: DMA handle + * @retval None + */ +static void SD_DMARxAbort(DMA_HandleTypeDef *hdma) +{ + SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent); + HAL_SD_CardStateTypeDef CardState; + + /* Clear All flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + CardState = HAL_SD_GetCardState(hsd); + hsd->State = HAL_SD_STATE_READY; + hsd->Context = SD_CONTEXT_NONE; + if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING)) + { + hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance); + } + + if(hsd->ErrorCode == HAL_SD_ERROR_NONE) + { +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->AbortCpltCallback(hsd); +#else + HAL_SD_AbortCallback(hsd); +#endif + } + else + { +#if (USE_HAL_SD_REGISTER_CALLBACKS == 1) + hsd->ErrorCallback(hsd); +#else + HAL_SD_ErrorCallback(hsd); +#endif + } +} + +/** + * @brief Initializes the sd card. + * @param hsd: Pointer to SD handle + * @retval SD Card error state + */ +static uint32_t SD_InitCard(SD_HandleTypeDef *hsd) +{ + HAL_SD_CardCSDTypeDef CSD; + uint32_t errorstate; + uint16_t sd_rca = 1U; + + /* Check the power State */ + if(SDIO_GetPowerState(hsd->Instance) == 0U) + { + /* Power off */ + return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE; + } + + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Send CMD2 ALL_SEND_CID */ + errorstate = SDMMC_CmdSendCID(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + else + { + /* Get Card identification number data */ + hsd->CID[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1); + hsd->CID[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2); + hsd->CID[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3); + hsd->CID[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4); + } + } + + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Send CMD3 SET_REL_ADDR with argument 0 */ + /* SD Card publishes its RCA. */ + errorstate = SDMMC_CmdSetRelAdd(hsd->Instance, &sd_rca); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + } + if(hsd->SdCard.CardType != CARD_SECURED) + { + /* Get the SD card RCA */ + hsd->SdCard.RelCardAdd = sd_rca; + + /* Send CMD9 SEND_CSD with argument as card's RCA */ + errorstate = SDMMC_CmdSendCSD(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + else + { + /* Get Card Specific Data */ + hsd->CSD[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1); + hsd->CSD[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2); + hsd->CSD[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3); + hsd->CSD[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4); + } + } + + /* Get the Card Class */ + hsd->SdCard.Class = (SDIO_GetResponse(hsd->Instance, SDIO_RESP2) >> 20U); + + /* Get CSD parameters */ + if (HAL_SD_GetCardCSD(hsd, &CSD) != HAL_OK) + { + return HAL_SD_ERROR_UNSUPPORTED_FEATURE; + } + + /* Select the Card */ + errorstate = SDMMC_CmdSelDesel(hsd->Instance, (uint32_t)(((uint32_t)hsd->SdCard.RelCardAdd) << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Configure SDIO peripheral interface */ + (void)SDIO_Init(hsd->Instance, hsd->Init); + + /* All cards are initialized */ + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Enquires cards about their operating voltage and configures clock + * controls and stores SD information that will be needed in future + * in the SD handle. + * @param hsd: Pointer to SD handle + * @retval error state + */ +static uint32_t SD_PowerON(SD_HandleTypeDef *hsd) +{ + __IO uint32_t count = 0U; + uint32_t response = 0U, validvoltage = 0U; + uint32_t errorstate; + + /* CMD0: GO_IDLE_STATE */ + errorstate = SDMMC_CmdGoIdleState(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* CMD8: SEND_IF_COND: Command available only on V2.0 cards */ + errorstate = SDMMC_CmdOperCond(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->SdCard.CardVersion = CARD_V1_X; + /* CMD0: GO_IDLE_STATE */ + errorstate = SDMMC_CmdGoIdleState(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + } + else + { + hsd->SdCard.CardVersion = CARD_V2_X; + } + + if( hsd->SdCard.CardVersion == CARD_V2_X) + { + /* SEND CMD55 APP_CMD with RCA as 0 */ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0); + if(errorstate != HAL_SD_ERROR_NONE) + { + return HAL_SD_ERROR_UNSUPPORTED_FEATURE; + } + } + /* SD CARD */ + /* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */ + while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U)) + { + /* SEND CMD55 APP_CMD with RCA as 0 */ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Send CMD41 */ + errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY); + if(errorstate != HAL_SD_ERROR_NONE) + { + return HAL_SD_ERROR_UNSUPPORTED_FEATURE; + } + + /* Get command response */ + response = SDIO_GetResponse(hsd->Instance, SDIO_RESP1); + + /* Get operating voltage*/ + validvoltage = (((response >> 31U) == 1U) ? 1U : 0U); + + count++; + } + + if(count >= SDMMC_MAX_VOLT_TRIAL) + { + return HAL_SD_ERROR_INVALID_VOLTRANGE; + } + + if((response & SDMMC_HIGH_CAPACITY) == SDMMC_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */ + { + hsd->SdCard.CardType = CARD_SDHC_SDXC; + } + else + { + hsd->SdCard.CardType = CARD_SDSC; + } + + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Turns the SDIO output signals off. + * @param hsd: Pointer to SD handle + * @retval None + */ +static void SD_PowerOFF(SD_HandleTypeDef *hsd) +{ + /* Set Power State to OFF */ + (void)SDIO_PowerState_OFF(hsd->Instance); +} + +/** + * @brief Send Status info command. + * @param hsd: pointer to SD handle + * @param pSDstatus: Pointer to the buffer that will contain the SD card status + * SD Status register) + * @retval error state + */ +static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t count; + uint32_t *pData = pSDstatus; + + /* Check SD response */ + if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + return HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + } + + /* Set block size for card if it is not equal to current block size for card */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= HAL_SD_ERROR_NONE; + return errorstate; + } + + /* Send CMD55 */ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= HAL_SD_ERROR_NONE; + return errorstate; + } + + /* Configure the SD DPSM (Data Path State Machine) */ + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = 64U; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_64B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Send ACMD13 (SD_APP_STAUS) with argument as card's RCA */ + errorstate = SDMMC_CmdStatusRegister(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + hsd->ErrorCode |= HAL_SD_ERROR_NONE; + return errorstate; + } + + /* Get status data */ + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND)) + { + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF)) + { + for(count = 0U; count < 8U; count++) + { + *pData = SDIO_ReadFIFO(hsd->Instance); + pData++; + } + } + + if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT) + { + return HAL_SD_ERROR_TIMEOUT; + } + } + + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) + { + return HAL_SD_ERROR_DATA_TIMEOUT; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL)) + { + return HAL_SD_ERROR_DATA_CRC_FAIL; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR)) + { + return HAL_SD_ERROR_RX_OVERRUN; + } + else + { + /* Nothing to do */ + } + + while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL))) + { + *pData = SDIO_ReadFIFO(hsd->Instance); + pData++; + + if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT) + { + return HAL_SD_ERROR_TIMEOUT; + } + } + + /* Clear all the static status flags*/ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Returns the current card's status. + * @param hsd: Pointer to SD handle + * @param pCardStatus: pointer to the buffer that will contain the SD card + * status (Card Status register) + * @retval error state + */ +static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus) +{ + uint32_t errorstate; + + if(pCardStatus == NULL) + { + return HAL_SD_ERROR_PARAM; + } + + /* Send Status command */ + errorstate = SDMMC_CmdSendStatus(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Get SD card status */ + *pCardStatus = SDIO_GetResponse(hsd->Instance, SDIO_RESP1); + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Enables the SDIO wide bus mode. + * @param hsd: pointer to SD handle + * @retval error state + */ +static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) +{ + uint32_t scr[2U] = {0U, 0U}; + uint32_t errorstate; + + if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + return HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + } + + /* Get SCR Register */ + errorstate = SD_FindSCR(hsd, scr); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* If requested card supports wide bus operation */ + if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO) + { + /* Send CMD55 APP_CMD with argument as card's RCA.*/ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ + errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + return HAL_SD_ERROR_NONE; + } + else + { + return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE; + } +} + +/** + * @brief Disables the SDIO wide bus mode. + * @param hsd: Pointer to SD handle + * @retval error state + */ +static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd) +{ + uint32_t scr[2U] = {0U, 0U}; + uint32_t errorstate; + + if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + return HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + } + + /* Get SCR Register */ + errorstate = SD_FindSCR(hsd, scr); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* If requested card supports 1 bit mode operation */ + if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO) + { + /* Send CMD55 APP_CMD with argument as card's RCA */ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Send ACMD6 APP_CMD with argument as 0 for single bus mode */ + errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + return HAL_SD_ERROR_NONE; + } + else + { + return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE; + } +} + + +/** + * @brief Finds the SD card SCR register value. + * @param hsd: Pointer to SD handle + * @param pSCR: pointer to the buffer that will contain the SCR value + * @retval error state + */ +static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR) +{ + SDIO_DataInitTypeDef config; + uint32_t errorstate; + uint32_t tickstart = HAL_GetTick(); + uint32_t index = 0U; + uint32_t tempscr[2U] = {0U, 0U}; + uint32_t *scr = pSCR; + + /* Set Block Size To 8 Bytes */ + errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + /* Send CMD55 APP_CMD with argument as card's RCA */ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U)); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + config.DataTimeOut = SDMMC_DATATIMEOUT; + config.DataLength = 8U; + config.DataBlockSize = SDIO_DATABLOCK_SIZE_8B; + config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO; + config.TransferMode = SDIO_TRANSFER_MODE_BLOCK; + config.DPSM = SDIO_DPSM_ENABLE; + (void)SDIO_ConfigData(hsd->Instance, &config); + + /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */ + errorstate = SDMMC_CmdSendSCR(hsd->Instance); + if(errorstate != HAL_SD_ERROR_NONE) + { + return errorstate; + } + + while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT)) + { + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)) + { + *(tempscr + index) = SDIO_ReadFIFO(hsd->Instance); + index++; + } + else if(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXACT)) + { + break; + } + + if((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT) + { + return HAL_SD_ERROR_TIMEOUT; + } + } + + if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) + { + __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DTIMEOUT); + + return HAL_SD_ERROR_DATA_TIMEOUT; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL)) + { + __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DCRCFAIL); + + return HAL_SD_ERROR_DATA_CRC_FAIL; + } + else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR)) + { + __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_RXOVERR); + + return HAL_SD_ERROR_RX_OVERRUN; + } + else + { + /* No error flag set */ + /* Clear all the static flags */ + __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); + + *scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24) | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\ + ((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24)); + scr++; + *scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24) | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\ + ((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24)); + + } + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Wrap up reading in non-blocking mode. + * @param hsd: pointer to a SD_HandleTypeDef structure that contains + * the configuration information. + * @retval None + */ +static void SD_Read_IT(SD_HandleTypeDef *hsd) +{ + uint32_t count, data, dataremaining; + uint8_t* tmp; + + tmp = hsd->pRxBuffPtr; + dataremaining = hsd->RxXferSize; + + if (dataremaining > 0U) + { + /* Read data from SDIO Rx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = SDIO_ReadFIFO(hsd->Instance); + *tmp = (uint8_t)(data & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 8U) & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 16U) & 0xFFU); + tmp++; + dataremaining--; + *tmp = (uint8_t)((data >> 24U) & 0xFFU); + tmp++; + dataremaining--; + } + + hsd->pRxBuffPtr = tmp; + hsd->RxXferSize = dataremaining; + } +} + +/** + * @brief Wrap up writing in non-blocking mode. + * @param hsd: pointer to a SD_HandleTypeDef structure that contains + * the configuration information. + * @retval None + */ +static void SD_Write_IT(SD_HandleTypeDef *hsd) +{ + uint32_t count, data, dataremaining; + uint8_t* tmp; + + tmp = hsd->pTxBuffPtr; + dataremaining = hsd->TxXferSize; + + if (dataremaining > 0U) + { + /* Write data to SDIO Tx FIFO */ + for(count = 0U; count < 8U; count++) + { + data = (uint32_t)(*tmp); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 8U); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 16U); + tmp++; + dataremaining--; + data |= ((uint32_t)(*tmp) << 24U); + tmp++; + dataremaining--; + (void)SDIO_WriteFIFO(hsd->Instance, &data); + } + + hsd->pTxBuffPtr = tmp; + hsd->TxXferSize = dataremaining; + } +} + +/** + * @} + */ + +#endif /* HAL_SD_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* SDIO */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c new file mode 100644 index 0000000..31633a2 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sdram.c @@ -0,0 +1,1308 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sdram.c + * @author MCD Application Team + * @brief SDRAM HAL module driver. + * This file provides a generic firmware to drive SDRAM memories mounted + * as external device. + * + ****************************************************************************** + * @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 ##### + ============================================================================== + [..] + This driver is a generic layered driver which contains a set of APIs used to + control SDRAM memories. It uses the FMC layer functions to interface + with SDRAM devices. + The following sequence should be followed to configure the FMC to interface + with SDRAM memories: + + (#) Declare a SDRAM_HandleTypeDef handle structure, for example: + SDRAM_HandleTypeDef hsdram + + (++) Fill the SDRAM_HandleTypeDef handle "Init" field with the allowed + values of the structure member. + + (++) Fill the SDRAM_HandleTypeDef handle "Instance" field with a predefined + base register instance for NOR or SDRAM device + + (#) Declare a FMC_SDRAM_TimingTypeDef structure; for example: + FMC_SDRAM_TimingTypeDef Timing; + and fill its fields with the allowed values of the structure member. + + (#) Initialize the SDRAM Controller by calling the function HAL_SDRAM_Init(). This function + performs the following sequence: + + (##) MSP hardware layer configuration using the function HAL_SDRAM_MspInit() + (##) Control register configuration using the FMC SDRAM interface function + FMC_SDRAM_Init() + (##) Timing register configuration using the FMC SDRAM interface function + FMC_SDRAM_Timing_Init() + (##) Program the SDRAM external device by applying its initialization sequence + according to the device plugged in your hardware. This step is mandatory + for accessing the SDRAM device. + + (#) At this stage you can perform read/write accesses from/to the memory connected + to the SDRAM Bank. You can perform either polling or DMA transfer using the + following APIs: + (++) HAL_SDRAM_Read()/HAL_SDRAM_Write() for polling read/write access + (++) HAL_SDRAM_Read_DMA()/HAL_SDRAM_Write_DMA() for DMA read/write transfer + + (#) You can also control the SDRAM device by calling the control APIs HAL_SDRAM_WriteOperation_Enable()/ + HAL_SDRAM_WriteOperation_Disable() to respectively enable/disable the SDRAM write operation or + the function HAL_SDRAM_SendCommand() to send a specified command to the SDRAM + device. The command to be sent must be configured with the FMC_SDRAM_CommandTypeDef + structure. + + (#) You can continuously monitor the SDRAM device HAL state by calling the function + HAL_SDRAM_GetState() + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_SDRAM_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_SDRAM_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) MspInitCallback : SDRAM MspInit. + (+) MspDeInitCallback : SDRAM MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_SDRAM_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) MspInitCallback : SDRAM MspInit. + (+) MspDeInitCallback : SDRAM MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_SDRAM_Init and if the state is HAL_SDRAM_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_SDRAM_Init + and HAL_SDRAM_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_SDRAM_Init and HAL_SDRAM_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_SDRAM_RegisterCallback before calling HAL_SDRAM_DeInit + or HAL_SDRAM_Init function. + + When The compilation define USE_HAL_SDRAM_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(FMC_Bank5_6) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + +/** @defgroup SDRAM SDRAM + * @brief SDRAM driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void SDRAM_DMACplt(DMA_HandleTypeDef *hdma); +static void SDRAM_DMACpltProt(DMA_HandleTypeDef *hdma); +static void SDRAM_DMAError(DMA_HandleTypeDef *hdma); + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SDRAM_Exported_Functions SDRAM Exported Functions + * @{ + */ + +/** @defgroup SDRAM_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### SDRAM Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to initialize/de-initialize + the SDRAM memory + +@endverbatim + * @{ + */ + +/** + * @brief Performs the SDRAM device initialization sequence. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param Timing Pointer to SDRAM control timing structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Init(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_TimingTypeDef *Timing) +{ + /* Check the SDRAM handle parameter */ + if (hsdram == NULL) + { + return HAL_ERROR; + } + + if (hsdram->State == HAL_SDRAM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsdram->Lock = HAL_UNLOCKED; +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + if (hsdram->MspInitCallback == NULL) + { + hsdram->MspInitCallback = HAL_SDRAM_MspInit; + } + hsdram->RefreshErrorCallback = HAL_SDRAM_RefreshErrorCallback; + hsdram->DmaXferCpltCallback = HAL_SDRAM_DMA_XferCpltCallback; + hsdram->DmaXferErrorCallback = HAL_SDRAM_DMA_XferErrorCallback; + + /* Init the low level hardware */ + hsdram->MspInitCallback(hsdram); +#else + /* Initialize the low level hardware (MSP) */ + HAL_SDRAM_MspInit(hsdram); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ + } + + /* Initialize the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Initialize SDRAM control Interface */ + (void)FMC_SDRAM_Init(hsdram->Instance, &(hsdram->Init)); + + /* Initialize SDRAM timing Interface */ + (void)FMC_SDRAM_Timing_Init(hsdram->Instance, Timing, hsdram->Init.SDBank); + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Perform the SDRAM device initialization sequence. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_DeInit(SDRAM_HandleTypeDef *hsdram) +{ +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + if (hsdram->MspDeInitCallback == NULL) + { + hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit; + } + + /* DeInit the low level hardware */ + hsdram->MspDeInitCallback(hsdram); +#else + /* Initialize the low level hardware (MSP) */ + HAL_SDRAM_MspDeInit(hsdram); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ + + /* Configure the SDRAM registers with their reset values */ + (void)FMC_SDRAM_DeInit(hsdram->Instance, hsdram->Init.SDBank); + + /* Reset the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hsdram); + + return HAL_OK; +} + +/** + * @brief SDRAM MSP Init. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval None + */ +__weak void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef *hsdram) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsdram); + + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_SDRAM_MspInit could be implemented in the user file + */ +} + +/** + * @brief SDRAM MSP DeInit. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval None + */ +__weak void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef *hsdram) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsdram); + + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_SDRAM_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief This function handles SDRAM refresh error interrupt request. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval HAL status + */ +void HAL_SDRAM_IRQHandler(SDRAM_HandleTypeDef *hsdram) +{ + /* Check SDRAM interrupt Rising edge flag */ + if (__FMC_SDRAM_GET_FLAG(hsdram->Instance, FMC_SDRAM_FLAG_REFRESH_IT)) + { + /* SDRAM refresh error interrupt callback */ +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + hsdram->RefreshErrorCallback(hsdram); +#else + HAL_SDRAM_RefreshErrorCallback(hsdram); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ + + /* Clear SDRAM refresh error interrupt pending bit */ + __FMC_SDRAM_CLEAR_FLAG(hsdram->Instance, FMC_SDRAM_FLAG_REFRESH_ERROR); + } +} + +/** + * @brief SDRAM Refresh error callback. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval None + */ +__weak void HAL_SDRAM_RefreshErrorCallback(SDRAM_HandleTypeDef *hsdram) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsdram); + + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_SDRAM_RefreshErrorCallback could be implemented in the user file + */ +} + +/** + * @brief DMA transfer complete callback. + * @param hdma pointer to a DMA_HandleTypeDef structure that contains + * the configuration information for the specified DMA module. + * @retval None + */ +__weak void HAL_SDRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_SDRAM_DMA_XferCpltCallback could be implemented in the user file + */ +} + +/** + * @brief DMA transfer complete error callback. + * @param hdma DMA handle + * @retval None + */ +__weak void HAL_SDRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* NOTE: This function Should not be modified, when the callback is needed, + the HAL_SDRAM_DMA_XferErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup SDRAM_Exported_Functions_Group2 Input and Output functions + * @brief Input Output and memory control functions + * + @verbatim + ============================================================================== + ##### SDRAM Input and Output functions ##### + ============================================================================== + [..] + This section provides functions allowing to use and control the SDRAM memory + +@endverbatim + * @{ + */ + +/** + * @brief Reads 8-bit data buffer from the SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Read_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint8_t *pSdramAddress = (uint8_t *)pAddress; + uint8_t *pdestbuff = pDstBuffer; + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Read data from source */ + for (size = BufferSize; size != 0U; size--) + { + *pdestbuff = *(__IO uint8_t *)pSdramAddress; + pdestbuff++; + pSdramAddress++; + } + + /* Update the SDRAM controller state */ + hsdram->State = state; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 8-bit data buffer to SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Write_8b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint8_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint8_t *pSdramAddress = (uint8_t *)pAddress; + uint8_t *psrcbuff = pSrcBuffer; + + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Write data to memory */ + for (size = BufferSize; size != 0U; size--) + { + *(__IO uint8_t *)pSdramAddress = *psrcbuff; + psrcbuff++; + pSdramAddress++; + } + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads 16-bit data buffer from the SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Read_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *pSdramAddress = pAddress; + uint16_t *pdestbuff = pDstBuffer; + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Read data from memory */ + for (size = BufferSize; size >= 2U ; size -= 2U) + { + *pdestbuff = (uint16_t)((*pSdramAddress) & 0x0000FFFFU); + pdestbuff++; + *pdestbuff = (uint16_t)(((*pSdramAddress) & 0xFFFF0000U) >> 16U); + pdestbuff++; + pSdramAddress++; + } + + /* Read last 16-bits if size is not 32-bits multiple */ + if ((BufferSize % 2U) != 0U) + { + *pdestbuff = (uint16_t)((*pSdramAddress) & 0x0000FFFFU); + } + + /* Update the SDRAM controller state */ + hsdram->State = state; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 16-bit data buffer to SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Write_16b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint16_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *psdramaddress = pAddress; + uint16_t *psrcbuff = pSrcBuffer; + + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Write data to memory */ + for (size = BufferSize; size >= 2U ; size -= 2U) + { + *psdramaddress = (uint32_t)(*psrcbuff); + psrcbuff++; + *psdramaddress |= ((uint32_t)(*psrcbuff) << 16U); + psrcbuff++; + psdramaddress++; + } + + /* Write last 16-bits if size is not 32-bits multiple */ + if ((BufferSize % 2U) != 0U) + { + *psdramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psdramaddress) & 0xFFFF0000U); + } + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads 32-bit data buffer from the SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Read_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *pSdramAddress = (uint32_t *)pAddress; + uint32_t *pdestbuff = pDstBuffer; + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Read data from source */ + for (size = BufferSize; size != 0U; size--) + { + *pdestbuff = *(__IO uint32_t *)pSdramAddress; + pdestbuff++; + pSdramAddress++; + } + + /* Update the SDRAM controller state */ + hsdram->State = state; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 32-bit data buffer to SDRAM memory. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Write_32b(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *pSdramAddress = pAddress; + uint32_t *psrcbuff = pSrcBuffer; + + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Write data to memory */ + for (size = BufferSize; size != 0U; size--) + { + *pSdramAddress = *psrcbuff; + psrcbuff++; + pSdramAddress++; + } + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads a Words data from the SDRAM memory using DMA transfer. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Read_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize) +{ + HAL_StatusTypeDef status; + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + status = HAL_BUSY; + } + else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Configure DMA user callbacks */ + if (state == HAL_SDRAM_STATE_READY) + { + hsdram->hdma->XferCpltCallback = SDRAM_DMACplt; + } + else + { + hsdram->hdma->XferCpltCallback = SDRAM_DMACpltProt; + } + hsdram->hdma->XferErrorCallback = SDRAM_DMAError; + + /* Enable the DMA Stream */ + status = HAL_DMA_Start_IT(hsdram->hdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)BufferSize); + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Writes a Words data buffer to SDRAM memory using DMA transfer. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_Write_DMA(SDRAM_HandleTypeDef *hsdram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize) +{ + HAL_StatusTypeDef status; + + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + status = HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsdram); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Configure DMA user callbacks */ + hsdram->hdma->XferCpltCallback = SDRAM_DMACplt; + hsdram->hdma->XferErrorCallback = SDRAM_DMAError; + + /* Enable the DMA Stream */ + status = HAL_DMA_Start_IT(hsdram->hdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)BufferSize); + + /* Process Unlocked */ + __HAL_UNLOCK(hsdram); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User SDRAM Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hsdram : SDRAM handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SDRAM_MSP_INIT_CB_ID SDRAM MspInit callback ID + * @arg @ref HAL_SDRAM_MSP_DEINIT_CB_ID SDRAM MspDeInit callback ID + * @arg @ref HAL_SDRAM_REFRESH_ERR_CB_ID SDRAM Refresh Error callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SDRAM_RegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId, + pSDRAM_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SDRAM_StateTypeDef state; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hsdram); + + state = hsdram->State; + if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SDRAM_MSP_INIT_CB_ID : + hsdram->MspInitCallback = pCallback; + break; + case HAL_SDRAM_MSP_DEINIT_CB_ID : + hsdram->MspDeInitCallback = pCallback; + break; + case HAL_SDRAM_REFRESH_ERR_CB_ID : + hsdram->RefreshErrorCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hsdram->State == HAL_SDRAM_STATE_RESET) + { + switch (CallbackId) + { + case HAL_SDRAM_MSP_INIT_CB_ID : + hsdram->MspInitCallback = pCallback; + break; + case HAL_SDRAM_MSP_DEINIT_CB_ID : + hsdram->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsdram); + return status; +} + +/** + * @brief Unregister a User SDRAM Callback + * SDRAM Callback is redirected to the weak (surcharged) predefined callback + * @param hsdram : SDRAM handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SDRAM_MSP_INIT_CB_ID SDRAM MspInit callback ID + * @arg @ref HAL_SDRAM_MSP_DEINIT_CB_ID SDRAM MspDeInit callback ID + * @arg @ref HAL_SDRAM_REFRESH_ERR_CB_ID SDRAM Refresh Error callback ID + * @arg @ref HAL_SDRAM_DMA_XFER_CPLT_CB_ID SDRAM DMA Xfer Complete callback ID + * @arg @ref HAL_SDRAM_DMA_XFER_ERR_CB_ID SDRAM DMA Xfer Error callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_SDRAM_UnRegisterCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SDRAM_StateTypeDef state; + + /* Process locked */ + __HAL_LOCK(hsdram); + + state = hsdram->State; + if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SDRAM_MSP_INIT_CB_ID : + hsdram->MspInitCallback = HAL_SDRAM_MspInit; + break; + case HAL_SDRAM_MSP_DEINIT_CB_ID : + hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit; + break; + case HAL_SDRAM_REFRESH_ERR_CB_ID : + hsdram->RefreshErrorCallback = HAL_SDRAM_RefreshErrorCallback; + break; + case HAL_SDRAM_DMA_XFER_CPLT_CB_ID : + hsdram->DmaXferCpltCallback = HAL_SDRAM_DMA_XferCpltCallback; + break; + case HAL_SDRAM_DMA_XFER_ERR_CB_ID : + hsdram->DmaXferErrorCallback = HAL_SDRAM_DMA_XferErrorCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (hsdram->State == HAL_SDRAM_STATE_RESET) + { + switch (CallbackId) + { + case HAL_SDRAM_MSP_INIT_CB_ID : + hsdram->MspInitCallback = HAL_SDRAM_MspInit; + break; + case HAL_SDRAM_MSP_DEINIT_CB_ID : + hsdram->MspDeInitCallback = HAL_SDRAM_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsdram); + return status; +} + +/** + * @brief Register a User SDRAM Callback for DMA transfers + * To be used instead of the weak (surcharged) predefined callback + * @param hsdram : SDRAM handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SDRAM_DMA_XFER_CPLT_CB_ID SDRAM DMA Xfer Complete callback ID + * @arg @ref HAL_SDRAM_DMA_XFER_ERR_CB_ID SDRAM DMA Xfer Error callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SDRAM_RegisterDmaCallback(SDRAM_HandleTypeDef *hsdram, HAL_SDRAM_CallbackIDTypeDef CallbackId, + pSDRAM_DmaCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SDRAM_StateTypeDef state; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hsdram); + + state = hsdram->State; + if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_WRITE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SDRAM_DMA_XFER_CPLT_CB_ID : + hsdram->DmaXferCpltCallback = pCallback; + break; + case HAL_SDRAM_DMA_XFER_ERR_CB_ID : + hsdram->DmaXferErrorCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsdram); + return status; +} +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SDRAM_Exported_Functions_Group3 Control functions + * @brief management functions + * +@verbatim + ============================================================================== + ##### SDRAM Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the SDRAM interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically SDRAM write protection. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Enable(SDRAM_HandleTypeDef *hsdram) +{ + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Enable write protection */ + (void)FMC_SDRAM_WriteProtection_Enable(hsdram->Instance, hsdram->Init.SDBank); + + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_WRITE_PROTECTED; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically SDRAM write protection. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_WriteProtection_Disable(SDRAM_HandleTypeDef *hsdram) +{ + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (state == HAL_SDRAM_STATE_WRITE_PROTECTED) + { + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Disable write protection */ + (void)FMC_SDRAM_WriteProtection_Disable(hsdram->Instance, hsdram->Init.SDBank); + + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Sends Command to the SDRAM bank. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param Command SDRAM command structure + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_SendCommand(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command, + uint32_t Timeout) +{ + HAL_SDRAM_StateTypeDef state = hsdram->State; + + /* Check the SDRAM controller state */ + if (state == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if ((state == HAL_SDRAM_STATE_READY) || (state == HAL_SDRAM_STATE_PRECHARGED)) + { + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Send SDRAM command */ + (void)FMC_SDRAM_SendCommand(hsdram->Instance, Command, Timeout); + + /* Update the SDRAM controller state state */ + if (Command->CommandMode == FMC_SDRAM_CMD_PALL) + { + hsdram->State = HAL_SDRAM_STATE_PRECHARGED; + } + else + { + hsdram->State = HAL_SDRAM_STATE_READY; + } + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Programs the SDRAM Memory Refresh rate. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param RefreshRate The SDRAM refresh rate value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_ProgramRefreshRate(SDRAM_HandleTypeDef *hsdram, uint32_t RefreshRate) +{ + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Program the refresh rate */ + (void)FMC_SDRAM_ProgramRefreshRate(hsdram->Instance, RefreshRate); + + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Sets the Number of consecutive SDRAM Memory auto Refresh commands. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @param AutoRefreshNumber The SDRAM auto Refresh number + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SDRAM_SetAutoRefreshNumber(SDRAM_HandleTypeDef *hsdram, uint32_t AutoRefreshNumber) +{ + /* Check the SDRAM controller state */ + if (hsdram->State == HAL_SDRAM_STATE_BUSY) + { + return HAL_BUSY; + } + else if (hsdram->State == HAL_SDRAM_STATE_READY) + { + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_BUSY; + + /* Set the Auto-Refresh number */ + (void)FMC_SDRAM_SetAutoRefreshNumber(hsdram->Instance, AutoRefreshNumber); + + /* Update the SDRAM state */ + hsdram->State = HAL_SDRAM_STATE_READY; + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Returns the SDRAM memory current mode. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval The SDRAM memory mode. + */ +uint32_t HAL_SDRAM_GetModeStatus(SDRAM_HandleTypeDef *hsdram) +{ + /* Return the SDRAM memory current mode */ + return (FMC_SDRAM_GetModeStatus(hsdram->Instance, hsdram->Init.SDBank)); +} + +/** + * @} + */ + +/** @defgroup SDRAM_Exported_Functions_Group4 State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### SDRAM State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the SDRAM controller + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Returns the SDRAM state. + * @param hsdram pointer to a SDRAM_HandleTypeDef structure that contains + * the configuration information for SDRAM module. + * @retval HAL state + */ +HAL_SDRAM_StateTypeDef HAL_SDRAM_GetState(SDRAM_HandleTypeDef *hsdram) +{ + return hsdram->State; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @brief DMA SDRAM process complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void SDRAM_DMACplt(DMA_HandleTypeDef *hdma) +{ + SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_READY; + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + hsdram->DmaXferCpltCallback(hdma); +#else + HAL_SDRAM_DMA_XferCpltCallback(hdma); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SRAM process complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void SDRAM_DMACpltProt(DMA_HandleTypeDef *hdma) +{ + SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_WRITE_PROTECTED; + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + hsdram->DmaXferCpltCallback(hdma); +#else + HAL_SDRAM_DMA_XferCpltCallback(hdma); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SDRAM error callback. + * @param hdma : DMA handle + * @retval None + */ +static void SDRAM_DMAError(DMA_HandleTypeDef *hdma) +{ + SDRAM_HandleTypeDef *hsdram = (SDRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SDRAM controller state */ + hsdram->State = HAL_SDRAM_STATE_ERROR; + +#if (USE_HAL_SDRAM_REGISTER_CALLBACKS == 1) + hsdram->DmaXferErrorCallback(hdma); +#else + HAL_SDRAM_DMA_XferErrorCallback(hdma); +#endif /* USE_HAL_SDRAM_REGISTER_CALLBACKS */ +} + +/** + * @} + */ + +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* FMC_Bank5_6 */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c new file mode 100644 index 0000000..9d165cd --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smartcard.c @@ -0,0 +1,2364 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_smartcard.c + * @author MCD Application Team + * @brief SMARTCARD HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the SMARTCARD peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Error 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 SMARTCARD HAL driver can be used as follows: + + (#) Declare a SMARTCARD_HandleTypeDef handle structure. + (#) Initialize the SMARTCARD low level resources by implementing the HAL_SMARTCARD_MspInit() API: + (##) Enable the interface clock of the USARTx associated to the SMARTCARD. + (##) SMARTCARD pins configuration: + (+++) Enable the clock for the SMARTCARD GPIOs. + (+++) Configure SMARTCARD pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_SMARTCARD_Transmit_IT() + and HAL_SMARTCARD_Receive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_SMARTCARD_Transmit_DMA() + and HAL_SMARTCARD_Receive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx stream. + (+++) Associate the initialized DMA handle to the SMARTCARD DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx stream. + (+++) 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 SMARTCARD Init structure. + + (#) Initialize the SMARTCARD registers by calling the HAL_SMARTCARD_Init() API: + (++) These APIs configure also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_SMARTCARD_MspInit() API. + [..] + (@) The specific SMARTCARD interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_SMARTCARD_ENABLE_IT() and __HAL_SMARTCARD_DISABLE_IT() inside the transmit and receive process. + + [..] + Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_SMARTCARD_Transmit() + (+) Receive an amount of data in blocking mode using HAL_SMARTCARD_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_SMARTCARD_Transmit_IT() + (+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_SMARTCARD_Receive_IT() + (+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback + (+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Transmit_DMA() + (+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Receive_DMA() + (+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback + (+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback + + *** SMARTCARD HAL driver macros list *** + ======================================== + [..] + Below the list of most used macros in SMARTCARD HAL driver. + + (+) __HAL_SMARTCARD_ENABLE: Enable the SMARTCARD peripheral + (+) __HAL_SMARTCARD_DISABLE: Disable the SMARTCARD peripheral + (+) __HAL_SMARTCARD_GET_FLAG : Check whether the specified SMARTCARD flag is set or not + (+) __HAL_SMARTCARD_CLEAR_FLAG : Clear the specified SMARTCARD pending flag + (+) __HAL_SMARTCARD_ENABLE_IT: Enable the specified SMARTCARD interrupt + (+) __HAL_SMARTCARD_DISABLE_IT: Disable the specified SMARTCARD interrupt + + [..] + (@) You can refer to the SMARTCARD HAL driver header file for more useful macros + + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function HAL_SMARTCARD_RegisterCallback() to register a user callback. + Function HAL_SMARTCARD_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback. + (+) AbortReceiveCpltCallback : Abort Receive Complete Callback. + (+) MspInitCallback : SMARTCARD MspInit. + (+) MspDeInitCallback : SMARTCARD MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function HAL_SMARTCARD_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + HAL_SMARTCARD_UnRegisterCallback() takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) AbortTransmitCpltCallback : Abort Transmit Complete Callback. + (+) AbortReceiveCpltCallback : Abort Receive Complete Callback. + (+) MspInitCallback : SMARTCARD MspInit. + (+) MspDeInitCallback : SMARTCARD MspDeInit. + + [..] + By default, after the HAL_SMARTCARD_Init() and when the state is HAL_SMARTCARD_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the HAL_SMARTCARD_Init() + and HAL_SMARTCARD_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_SMARTCARD_Init() and HAL_SMARTCARD_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_SMARTCARD_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_SMARTCARD_STATE_READY or HAL_SMARTCARD_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_SMARTCARD_RegisterCallback() before calling HAL_SMARTCARD_DeInit() + or HAL_SMARTCARD_Init() function. + + [..] + When The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SMARTCARD SMARTCARD + * @brief HAL SMARTCARD module driver + * @{ + */ +#ifdef HAL_SMARTCARD_MODULE_ENABLED +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup SMARTCARD_Private_Constants + * @{ + */ +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup SMARTCARD_Private_Functions + * @{ + */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ +static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc); +static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc); +static void SMARTCARD_SetConfig (SMARTCARD_HandleTypeDef *hsc); +static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc); +static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc); +static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc); +static void SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMAError(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SMARTCARD_Exported_Functions SMARTCARD Exported Functions + * @{ + */ + +/** @defgroup SMARTCARD_Exported_Functions_Group1 SmartCard 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 USART + in Smartcard mode. + [..] + The Smartcard interface is designed to support asynchronous protocol Smartcards as + defined in the ISO 7816-3 standard. + [..] + The USART can provide a clock to the smartcard through the SCLK output. + In smartcard mode, SCLK is not associated to the communication but is simply derived + from the internal peripheral input clock through a 5-bit prescaler. + [..] + (+) For the Smartcard mode only these parameters can be configured: + (++) Baud Rate + (++) Word Length => Should be 9 bits (8 bits + parity) + (++) Stop Bit + (++) Parity: => Should be enabled + (++) USART polarity + (++) USART phase + (++) USART LastBit + (++) Receiver/transmitter modes + (++) Prescaler + (++) GuardTime + (++) NACKState: The Smartcard NACK state + + (+) Recommended SmartCard interface configuration to get the Answer to Reset from the Card: + (++) Word Length = 9 Bits + (++) 1.5 Stop Bit + (++) Even parity + (++) BaudRate = 12096 baud + (++) Tx and Rx enabled + [..] + Please refer to the ISO 7816-3 specification for more details. + + [..] + (@) It is also possible to choose 0.5 stop bit for receiving but it is recommended + to use 1.5 stop bits for both transmitting and receiving to avoid switching + between the two configurations. + [..] + The HAL_SMARTCARD_Init() function follows the USART SmartCard configuration + procedures (details for the procedures are available in reference manual + (RM0430 for STM32F4X3xx MCUs and RM0402 for STM32F412xx MCUs + RM0383 for STM32F411xC/E MCUs and RM0401 for STM32F410xx MCUs + RM0090 for STM32F4X5xx/STM32F4X7xx/STM32F429xx/STM32F439xx MCUs + RM0390 for STM32F446xx MCUs and RM0386 for STM32F469xx/STM32F479xx MCUs)). + +@endverbatim + + The SMARTCARD frame format is given in the following table: + +-------------------------------------------------------------+ + | M bit | PCE bit | SMARTCARD frame | + |---------------------|---------------------------------------| + | 1 | 1 | | SB | 8 bit data | PB | STB | | + +-------------------------------------------------------------+ + * @{ + */ + +/** + * @brief Initializes the SmartCard mode according to the specified + * parameters in the SMARTCARD_InitTypeDef and create the associated handle. + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsc) +{ + /* Check the SMARTCARD handle allocation */ + if(hsc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance)); + assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState)); + + if(hsc->gState == HAL_SMARTCARD_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsc->Lock = HAL_UNLOCKED; + +#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1 + SMARTCARD_InitCallbacksToDefault(hsc); + + if (hsc->MspInitCallback == NULL) + { + hsc->MspInitCallback = HAL_SMARTCARD_MspInit; + } + + /* Init the low level hardware */ + hsc->MspInitCallback(hsc); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_SMARTCARD_MspInit(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + } + + hsc->gState = HAL_SMARTCARD_STATE_BUSY; + + /* Set the Prescaler */ + MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_PSC, hsc->Init.Prescaler); + + /* Set the Guard Time */ + MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_GT, ((hsc->Init.GuardTime)<<8U)); + + /* Set the Smartcard Communication parameters */ + SMARTCARD_SetConfig(hsc); + + /* In SmartCard mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register + - HDSEL and IREN bits in the USART_CR3 register.*/ + CLEAR_BIT(hsc->Instance->CR2, USART_CR2_LINEN); + CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_IREN | USART_CR3_HDSEL)); + + /* Enable the SMARTCARD Parity Error Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE); + + /* Enable the SMARTCARD Framing Error Interrupt */ + SET_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Enable the Peripheral */ + __HAL_SMARTCARD_ENABLE(hsc); + + /* Configure the Smartcard NACK state */ + MODIFY_REG(hsc->Instance->CR3, USART_CR3_NACK, hsc->Init.NACKState); + + /* Enable the SC mode by setting the SCEN bit in the CR3 register */ + hsc->Instance->CR3 |= (USART_CR3_SCEN); + + /* Initialize the SMARTCARD state*/ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->gState= HAL_SMARTCARD_STATE_READY; + hsc->RxState= HAL_SMARTCARD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the USART SmartCard peripheral + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_DeInit(SMARTCARD_HandleTypeDef *hsc) +{ + /* Check the SMARTCARD handle allocation */ + if(hsc == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance)); + + hsc->gState = HAL_SMARTCARD_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_SMARTCARD_DISABLE(hsc); + + /* DeInit the low level hardware */ +#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1 + if (hsc->MspDeInitCallback == NULL) + { + hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; + } + /* DeInit the low level hardware */ + hsc->MspDeInitCallback(hsc); +#else + HAL_SMARTCARD_MspDeInit(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->gState = HAL_SMARTCARD_STATE_RESET; + hsc->RxState = HAL_SMARTCARD_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hsc); + + return HAL_OK; +} + +/** + * @brief SMARTCARD MSP Init + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +__weak void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_MspInit can be implemented in the user file + */ +} + +/** + * @brief SMARTCARD MSP DeInit + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +__weak void HAL_SMARTCARD_MspDeInit(SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_MspDeInit can be implemented in the user file + */ +} + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User SMARTCARD Callback + * To be used instead of the weak predefined callback + * @param hsc smartcard handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_RegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID, pSMARTCARD_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hsc); + + if (hsc->gState == HAL_SMARTCARD_STATE_READY) + { + switch (CallbackID) + { + + case HAL_SMARTCARD_TX_COMPLETE_CB_ID : + hsc->TxCpltCallback = pCallback; + break; + + case HAL_SMARTCARD_RX_COMPLETE_CB_ID : + hsc->RxCpltCallback = pCallback; + break; + + case HAL_SMARTCARD_ERROR_CB_ID : + hsc->ErrorCallback = pCallback; + break; + + case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID : + hsc->AbortCpltCallback = pCallback; + break; + + case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID : + hsc->AbortTransmitCpltCallback = pCallback; + break; + + case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID : + hsc->AbortReceiveCpltCallback = pCallback; + break; + + + case HAL_SMARTCARD_MSPINIT_CB_ID : + hsc->MspInitCallback = pCallback; + break; + + case HAL_SMARTCARD_MSPDEINIT_CB_ID : + hsc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (hsc->gState == HAL_SMARTCARD_STATE_RESET) + { + switch (CallbackID) + { + case HAL_SMARTCARD_MSPINIT_CB_ID : + hsc->MspInitCallback = pCallback; + break; + + case HAL_SMARTCARD_MSPDEINIT_CB_ID : + hsc->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsc); + + return status; +} + +/** + * @brief Unregister an SMARTCARD callback + * SMARTCARD callback is redirected to the weak predefined callback + * @param hsc smartcard handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID + * @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID + * @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_UnRegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hsc); + + if (HAL_SMARTCARD_STATE_READY == hsc->gState) + { + switch (CallbackID) + { + case HAL_SMARTCARD_TX_COMPLETE_CB_ID : + hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_SMARTCARD_RX_COMPLETE_CB_ID : + hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_SMARTCARD_ERROR_CB_ID : + hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID : + hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID : + hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + break; + + case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID : + hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + break; + + + case HAL_SMARTCARD_MSPINIT_CB_ID : + hsc->MspInitCallback = HAL_SMARTCARD_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_SMARTCARD_MSPDEINIT_CB_ID : + hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SMARTCARD_STATE_RESET == hsc->gState) + { + switch (CallbackID) + { + case HAL_SMARTCARD_MSPINIT_CB_ID : + hsc->MspInitCallback = HAL_SMARTCARD_MspInit; + break; + + case HAL_SMARTCARD_MSPDEINIT_CB_ID : + hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; + break; + + default : + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsc); + + return status; +} +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SMARTCARD_Exported_Functions_Group2 IO operation functions + * @brief SMARTCARD Transmit and Receive functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SMARTCARD data transfers. + + [..] + (#) Smartcard is a single wire half duplex communication protocol. + The Smartcard interface is designed to support asynchronous protocol Smartcards as + defined in the ISO 7816-3 standard. + (#) The USART should be configured as: + (++) 8 bits plus parity: where M=1 and PCE=1 in the USART_CR1 register + (++) 1.5 stop bits when transmitting and receiving: where STOP=11 in the USART_CR2 register. + + (#) 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 APIs return the HAL status. + The end of the data processing will be indicated through the + dedicated SMARTCARD IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback() user callbacks + will be executed respectively at the end of the Transmit or Receive process + The HAL_SMARTCARD_ErrorCallback() user callback will be executed when a communication error is detected + + (#) Blocking mode APIs are : + (++) HAL_SMARTCARD_Transmit() + (++) HAL_SMARTCARD_Receive() + + (#) Non Blocking mode APIs with Interrupt are : + (++) HAL_SMARTCARD_Transmit_IT() + (++) HAL_SMARTCARD_Receive_IT() + (++) HAL_SMARTCARD_IRQHandler() + + (#) Non Blocking mode functions with DMA are : + (++) HAL_SMARTCARD_Transmit_DMA() + (++) HAL_SMARTCARD_Receive_DMA() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_SMARTCARD_TxCpltCallback() + (++) HAL_SMARTCARD_RxCpltCallback() + (++) HAL_SMARTCARD_ErrorCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_SMARTCARD_Abort() + (+) HAL_SMARTCARD_AbortTransmit() + (+) HAL_SMARTCARD_AbortReceive() + (+) HAL_SMARTCARD_Abort_IT() + (+) HAL_SMARTCARD_AbortTransmit_IT() + (+) HAL_SMARTCARD_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_SMARTCARD_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_SMARTCARD_AbortCpltCallback() + (+) HAL_SMARTCARD_AbortTransmitCpltCallback() + (+) HAL_SMARTCARD_AbortReceiveCpltCallback() + + (#) 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_SMARTCARD_ErrorCallback() user callback is executed. Transfer is kept ongoing on SMARTCARD 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 Frame Error in Interrupt mode transmission, 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_SMARTCARD_ErrorCallback() user callback is executed. + +@endverbatim + * @{ + */ + +/** + * @brief Send an amount of data in blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Transmit(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + const uint8_t *tmp = pData; + uint32_t tickstart = 0U; + + if(hsc->gState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + hsc->TxXferSize = Size; + hsc->TxXferCount = Size; + while(hsc->TxXferCount > 0U) + { + hsc->TxXferCount--; + if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + hsc->Instance->DR = (uint8_t)(*tmp & 0xFFU); + tmp++; + } + + if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* At end of Tx process, restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Receive(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint8_t *tmp = pData; + uint32_t tickstart = 0U; + + if(hsc->RxState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + hsc->RxXferSize = Size; + hsc->RxXferCount = Size; + + /* Check the remain data to be received */ + while(hsc->RxXferCount > 0U) + { + hsc->RxXferCount--; + if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + *tmp = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU); + tmp++; + } + + /* At end of Rx process, restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size) +{ + /* Check that a Tx process is not already ongoing */ + if(hsc->gState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->pTxBuffPtr = pData; + hsc->TxXferSize = Size; + hsc->TxXferCount = Size; + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX; + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + /* Enable the SMARTCARD Parity Error Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE); + + /* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Enable the SMARTCARD Transmit data register empty Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_TXEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size) +{ + /* Check that a Rx process is not already ongoing */ + if(hsc->RxState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->pRxBuffPtr = pData; + hsc->RxXferSize = Size; + hsc->RxXferCount = Size; + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX; + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + /* Enable the SMARTCARD Parity Error and Data Register not empty Interrupts */ + SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE| USART_CR1_RXNEIE); + + /* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Send an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Transmit_DMA(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size) +{ + const uint32_t *tmp; + + /* Check that a Tx process is not already ongoing */ + if(hsc->gState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->pTxBuffPtr = pData; + hsc->TxXferSize = Size; + hsc->TxXferCount = Size; + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX; + + /* Set the SMARTCARD DMA transfer complete callback */ + hsc->hdmatx->XferCpltCallback = SMARTCARD_DMATransmitCplt; + + /* Set the DMA error callback */ + hsc->hdmatx->XferErrorCallback = SMARTCARD_DMAError; + + /* Set the DMA abort callback */ + hsc->hdmatx->XferAbortCallback = NULL; + + /* Enable the SMARTCARD transmit DMA stream */ + tmp = (const uint32_t*)&pData; + HAL_DMA_Start_IT(hsc->hdmatx, *(const uint32_t*)tmp, (uint32_t)&hsc->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_SMARTCARD_CLEAR_FLAG(hsc, SMARTCARD_FLAG_TC); + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the SMARTCARD CR3 register */ + SET_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @note When the SMARTCARD parity is enabled (PCE = 1) the data received contain the parity bit.s + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMARTCARD_Receive_DMA(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size) +{ + uint32_t *tmp; + + /* Check that a Rx process is not already ongoing */ + if(hsc->RxState == HAL_SMARTCARD_STATE_READY) + { + if((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsc); + + hsc->pRxBuffPtr = pData; + hsc->RxXferSize = Size; + + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX; + + /* Set the SMARTCARD DMA transfer complete callback */ + hsc->hdmarx->XferCpltCallback = SMARTCARD_DMAReceiveCplt; + + /* Set the DMA error callback */ + hsc->hdmarx->XferErrorCallback = SMARTCARD_DMAError; + + /* Set the DMA abort callback */ + hsc->hdmatx->XferAbortCallback = NULL; + + /* Enable the DMA stream */ + tmp = (uint32_t*)&pData; + HAL_DMA_Start_IT(hsc->hdmarx, (uint32_t)&hsc->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_SMARTCARD_CLEAR_OREFLAG(hsc); + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + /* Enable the SMARTCARD Parity Error Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE); + + /* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the SMARTCARD CR3 register */ + SET_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_SMARTCARD_Abort(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Disable the SMARTCARD DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + /* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmatx != NULL) + { + /* Set the SMARTCARD DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hsc->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hsc->hdmatx); + } + } + + /* Disable the SMARTCARD DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmarx != NULL) + { + /* Set the SMARTCARD DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hsc->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hsc->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + hsc->TxXferCount = 0x00U; + hsc->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + + /* Restore hsc->RxState and hsc->gState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + hsc->gState = HAL_SMARTCARD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SMARTCARD 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_SMARTCARD_AbortTransmit(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the SMARTCARD DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + /* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmatx != NULL) + { + /* Set the SMARTCARD DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hsc->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hsc->hdmatx); + } + } + + /* Reset Tx transfer counter */ + hsc->TxXferCount = 0x00U; + + /* Restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (blocking mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_SMARTCARD_AbortReceive(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Disable the SMARTCARD DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmarx != NULL) + { + /* Set the SMARTCARD DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + hsc->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(hsc->hdmarx); + } + } + + /* Reset Rx transfer counter */ + hsc->RxXferCount = 0x00U; + + /* Restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (Interrupt mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts + * - 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_SMARTCARD_Abort_IT(SMARTCARD_HandleTypeDef *hsc) +{ + uint32_t AbortCplt = 0x01U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to SMARTCARD Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if(hsc->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if SMARTCARD DMA Tx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT)) + { + hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxAbortCallback; + } + else + { + hsc->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if(hsc->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if SMARTCARD DMA Rx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxAbortCallback; + } + else + { + hsc->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the SMARTCARD DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at SMARTCARD level */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + /* Abort the SMARTCARD DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(hsc->hdmatx != NULL) + { + /* SMARTCARD Tx DMA Abort callback has already been initialised : + will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK) + { + hsc->hdmatx->XferAbortCallback = NULL; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* Disable the SMARTCARD DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* Abort the SMARTCARD DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(hsc->hdmarx != NULL) + { + /* SMARTCARD Rx DMA Abort callback has already been initialised : + will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK) + { + hsc->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 */ + hsc->TxXferCount = 0x00U; + hsc->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + + /* Restore hsc->gState and hsc->RxState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hsc->AbortCpltCallback(hsc); +#else + /* Call legacy weak Abort complete callback */ + HAL_SMARTCARD_AbortCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (Interrupt mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SMARTCARD 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_SMARTCARD_AbortTransmit_IT(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* Disable the SMARTCARD DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + /* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmatx != NULL) + { + /* Set the SMARTCARD DMA Abort callback : + will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */ + hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK) + { + /* Call Directly hsc->hdmatx->XferAbortCallback function in case of error */ + hsc->hdmatx->XferAbortCallback(hsc->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + hsc->TxXferCount = 0x00U; + + /* Restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hsc->AbortTransmitCpltCallback(hsc); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_SMARTCARD_AbortTransmitCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + } + else + { + /* Reset Tx transfer counter */ + hsc->TxXferCount = 0x00U; + + /* Restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hsc->AbortTransmitCpltCallback(hsc); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_SMARTCARD_AbortTransmitCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param hsc SMARTCARD handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SMARTCARD 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_SMARTCARD_AbortReceive_IT(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Disable the SMARTCARD DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(hsc->hdmarx != NULL) + { + /* Set the SMARTCARD DMA Abort callback : + will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */ + hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK) + { + /* Call Directly hsc->hdmarx->XferAbortCallback function in case of error */ + hsc->hdmarx->XferAbortCallback(hsc->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + hsc->RxXferCount = 0x00U; + + /* Restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hsc->AbortReceiveCpltCallback(hsc); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_SMARTCARD_AbortReceiveCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + } + else + { + /* Reset Rx transfer counter */ + hsc->RxXferCount = 0x00U; + + /* Restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hsc->AbortReceiveCpltCallback(hsc); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_SMARTCARD_AbortReceiveCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + + return HAL_OK; +} + +/** + * @brief This function handles SMARTCARD interrupt request. + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +void HAL_SMARTCARD_IRQHandler(SMARTCARD_HandleTypeDef *hsc) +{ + uint32_t isrflags = READ_REG(hsc->Instance->SR); + uint32_t cr1its = READ_REG(hsc->Instance->CR1); + uint32_t cr3its = READ_REG(hsc->Instance->CR3); + uint32_t dmarequest = 0x00U; + uint32_t errorflags = 0x00U; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE)); + if(errorflags == RESET) + { + /* SMARTCARD in mode Receiver -------------------------------------------------*/ + if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + SMARTCARD_Receive_IT(hsc); + return; + } + } + + /* If some errors occur */ + if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) + { + /* SMARTCARD parity error interrupt occurred ---------------------------*/ + if(((isrflags & SMARTCARD_FLAG_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_PE; + } + + /* SMARTCARD frame error interrupt occurred ----------------------------*/ + if(((isrflags & SMARTCARD_FLAG_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_FE; + } + + /* SMARTCARD noise error interrupt occurred ----------------------------*/ + if(((isrflags & SMARTCARD_FLAG_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_NE; + } + + /* SMARTCARD Over-Run interrupt occurred -------------------------------*/ + if(((isrflags & SMARTCARD_FLAG_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET))) + { + hsc->ErrorCode |= HAL_SMARTCARD_ERROR_ORE; + } + /* Call the Error call Back in case of Errors --------------------------*/ + if(hsc->ErrorCode != HAL_SMARTCARD_ERROR_NONE) + { + /* SMARTCARD in mode Receiver ----------------------------------------*/ + if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + SMARTCARD_Receive_IT(hsc); + } + + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR); + if(((hsc->ErrorCode & HAL_SMARTCARD_ERROR_ORE) != RESET) || dmarequest) + { + /* Blocking error : transfer is aborted + Set the SMARTCARD state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + SMARTCARD_EndRxTransfer(hsc); + /* Disable the SMARTCARD DMA Rx request if enabled */ + if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* Abort the SMARTCARD DMA Rx channel */ + if(hsc->hdmarx != NULL) + { + /* Set the SMARTCARD DMA Abort callback : + will lead to call HAL_SMARTCARD_ErrorCallback() at end of DMA abort procedure */ + hsc->hdmarx->XferAbortCallback = SMARTCARD_DMAAbortOnError; + + if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + hsc->hdmarx->XferAbortCallback(hsc->hdmarx); + } + } + else + { +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hsc->ErrorCallback(hsc); +#else + /* Call legacy weak user error callback */ + HAL_SMARTCARD_ErrorCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + } + else + { +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hsc->ErrorCallback(hsc); +#else + /* Call legacy weak user error callback */ + HAL_SMARTCARD_ErrorCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hsc->ErrorCallback(hsc); +#else + /* Call legacy weak user error callback */ + HAL_SMARTCARD_ErrorCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + } + } + return; + } /* End if some error occurs */ + + /* SMARTCARD in mode Transmitter ------------------------------------------*/ + if(((isrflags & SMARTCARD_FLAG_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) + { + SMARTCARD_Transmit_IT(hsc); + return; + } + + /* SMARTCARD in mode Transmitter (transmission end) -----------------------*/ + if(((isrflags & SMARTCARD_FLAG_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + SMARTCARD_EndTransmit_IT(hsc); + return; + } +} + +/** + * @brief Tx Transfer completed callbacks + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +__weak void HAL_SMARTCARD_TxCpltCallback(SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_TxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief Rx Transfer completed callback + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +__weak void HAL_SMARTCARD_RxCpltCallback(SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_RxCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief SMARTCARD error callback + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +__weak void HAL_SMARTCARD_ErrorCallback(SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief SMARTCARD Abort Complete callback. + * @param hsc SMARTCARD handle. + * @retval None + */ +__weak void HAL_SMARTCARD_AbortCpltCallback (SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief SMARTCARD Abort Transmit Complete callback. + * @param hsc SMARTCARD handle. + * @retval None + */ +__weak void HAL_SMARTCARD_AbortTransmitCpltCallback (SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_AbortTransmitCpltCallback can be implemented in the user file. + */ +} + +/** + * @brief SMARTCARD Abort Receive Complete callback. + * @param hsc SMARTCARD handle. + * @retval None + */ +__weak void HAL_SMARTCARD_AbortReceiveCpltCallback (SMARTCARD_HandleTypeDef *hsc) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsc); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMARTCARD_AbortReceiveCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup SMARTCARD_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief SMARTCARD State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the SmartCard. + (+) HAL_SMARTCARD_GetState() API can be helpful to check in run-time the state of the SmartCard peripheral. + (+) HAL_SMARTCARD_GetError() check in run-time errors that could be occurred during communication. +@endverbatim + * @{ + */ + +/** + * @brief Return the SMARTCARD handle state + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval HAL state + */ +HAL_SMARTCARD_StateTypeDef HAL_SMARTCARD_GetState(const SMARTCARD_HandleTypeDef *hsc) +{ + uint32_t temp1= 0x00U, temp2 = 0x00U; + temp1 = hsc->gState; + temp2 = hsc->RxState; + + return (HAL_SMARTCARD_StateTypeDef)(temp1 | temp2); +} + +/** + * @brief Return the SMARTCARD error code + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for the specified SMARTCARD. + * @retval SMARTCARD Error Code + */ +uint32_t HAL_SMARTCARD_GetError(const SMARTCARD_HandleTypeDef *hsc) +{ + return hsc->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @defgroup SMARTCARD_Private_Functions SMARTCARD Private Functions + * @{ + */ + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) +/** + * @brief Initialize the callbacks to their default values. + * @param hsc SMARTCARD handle. + * @retval none + */ +void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc) +{ + /* Init the SMARTCARD Callback settings */ + hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */ + hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */ + hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */ + +} +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */ + +/** + * @brief DMA SMARTCARD 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 SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT); + + /* Enable the SMARTCARD Transmit Complete Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE); +} + +/** + * @brief DMA SMARTCARD 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 SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->RxXferCount = 0U; + + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Rx complete callback */ + hsc->RxCpltCallback(hsc); +#else + /* Call legacy weak Rx complete callback */ + HAL_SMARTCARD_RxCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief DMA SMARTCARD 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 SMARTCARD_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t dmarequest = 0x00U; + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + hsc->RxXferCount = 0U; + hsc->TxXferCount = 0U; + hsc->ErrorCode = HAL_SMARTCARD_ERROR_DMA; + + /* Stop SMARTCARD DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT); + if((hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX) && dmarequest) + { + SMARTCARD_EndTxTransfer(hsc); + } + + /* Stop SMARTCARD DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR); + if((hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX) && dmarequest) + { + SMARTCARD_EndRxTransfer(hsc); + } + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hsc->ErrorCallback(hsc); +#else + /* Call legacy weak user error callback */ + HAL_SMARTCARD_ErrorCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief This function handles SMARTCARD Communication Timeout. It waits + * until a flag is no longer in the specified status. + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @param Flag Specifies the SMARTCARD flag to check. + * @param Status The actual Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while((__HAL_SMARTCARD_GET_FLAG(hsc, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) + { + if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout)) + { + /* Disable TXE and RXNE interrupts for the interrupt process */ + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE); + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE); + + hsc->gState= HAL_SMARTCARD_STATE_READY; + hsc->RxState= HAL_SMARTCARD_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsc); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief End ongoing Tx transfer on SMARTCARD peripheral (following error detection or Transmit completion). + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc) +{ + /* At end of Tx process, restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); +} + + +/** + * @brief End ongoing Rx transfer on SMARTCARD peripheral (following error detection or Reception completion). + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc) +{ + /* At end of Rx process, restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); +} + +/** + * @brief Send an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval HAL status + */ +static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc) +{ + + /* Check that a Tx process is ongoing */ + if(hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX) + { + hsc->Instance->DR = (uint8_t)(*hsc->pTxBuffPtr & 0xFFU); + hsc->pTxBuffPtr++; + + if(--hsc->TxXferCount == 0U) + { + /* Disable the SMARTCARD Transmit data register empty Interrupt */ + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE); + + /* Enable the SMARTCARD Transmit Complete Interrupt */ + SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE); + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Wraps up transmission in non blocking mode. + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for the specified SMARTCARD module. + * @retval HAL status + */ +static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc) +{ + /* Disable the SMARTCARD Transmit Complete Interrupt */ + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TCIE); + + /* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Tx process is ended, restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Tx complete callback */ + hsc->TxCpltCallback(hsc); +#else + /* Call legacy weak Tx complete callback */ + HAL_SMARTCARD_TxCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + + return HAL_OK; +} + +/** + * @brief Receive an amount of data in non blocking mode + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval HAL status + */ +static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc) +{ + + /* Check that a Rx process is ongoing */ + if(hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX) + { + *hsc->pRxBuffPtr = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU); + hsc->pRxBuffPtr++; + + if(--hsc->RxXferCount == 0U) + { + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE); + + /* Disable the SMARTCARD Parity Error Interrupt */ + CLEAR_BIT(hsc->Instance->CR1, USART_CR1_PEIE); + + /* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Rx complete callback */ + hsc->RxCpltCallback(hsc); +#else + /* Call legacy weak Rx complete callback */ + HAL_SMARTCARD_RxCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ + + return HAL_OK; + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief DMA SMARTCARD communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = (SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + hsc->RxXferCount = 0x00U; + hsc->TxXferCount = 0x00U; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered user error callback */ + hsc->ErrorCallback(hsc); +#else + /* Call legacy weak user error callback */ + HAL_SMARTCARD_ErrorCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief DMA SMARTCARD 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 DMA handle. + * @retval None + */ +static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(hsc->hdmarx != NULL) + { + if(hsc->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + hsc->TxXferCount = 0x00U; + hsc->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + + /* Restore hsc->gState and hsc->RxState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + hsc->RxState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hsc->AbortCpltCallback(hsc); +#else + /* Call legacy weak Abort complete callback */ + HAL_SMARTCARD_AbortCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief DMA SMARTCARD 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 DMA handle. + * @retval None + */ +static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(hsc->hdmatx != NULL) + { + if(hsc->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + hsc->TxXferCount = 0x00U; + hsc->RxXferCount = 0x00U; + + /* Reset ErrorCode */ + hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE; + + /* Restore hsc->gState and hsc->RxState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + hsc->RxState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort complete callback */ + hsc->AbortCpltCallback(hsc); +#else + /* Call legacy weak Abort complete callback */ + HAL_SMARTCARD_AbortCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief DMA SMARTCARD Tx communication abort callback, when initiated by user by a call to + * HAL_SMARTCARD_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 DMA handle. + * @retval None + */ +static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->TxXferCount = 0x00U; + + /* Restore hsc->gState to Ready */ + hsc->gState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Transmit Complete Callback */ + hsc->AbortTransmitCpltCallback(hsc); +#else + /* Call legacy weak Abort Transmit Complete Callback */ + HAL_SMARTCARD_AbortTransmitCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief DMA SMARTCARD Rx communication abort callback, when initiated by user by a call to + * HAL_SMARTCARD_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 DMA handle. + * @retval None + */ +static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + hsc->RxXferCount = 0x00U; + + /* Restore hsc->RxState to Ready */ + hsc->RxState = HAL_SMARTCARD_STATE_READY; + +#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1) + /* Call registered Abort Receive Complete Callback */ + hsc->AbortReceiveCpltCallback(hsc); +#else + /* Call legacy weak Abort Receive Complete Callback */ + HAL_SMARTCARD_AbortReceiveCpltCallback(hsc); +#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */ +} + +/** + * @brief Configure the SMARTCARD peripheral + * @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains + * the configuration information for SMARTCARD module. + * @retval None + */ +static void SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsc) +{ + uint32_t tmpreg = 0x00U; + uint32_t pclk; + + /* Check the parameters */ + assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance)); + assert_param(IS_SMARTCARD_POLARITY(hsc->Init.CLKPolarity)); + assert_param(IS_SMARTCARD_PHASE(hsc->Init.CLKPhase)); + assert_param(IS_SMARTCARD_LASTBIT(hsc->Init.CLKLastBit)); + assert_param(IS_SMARTCARD_BAUDRATE(hsc->Init.BaudRate)); + assert_param(IS_SMARTCARD_WORD_LENGTH(hsc->Init.WordLength)); + assert_param(IS_SMARTCARD_STOPBITS(hsc->Init.StopBits)); + assert_param(IS_SMARTCARD_PARITY(hsc->Init.Parity)); + assert_param(IS_SMARTCARD_MODE(hsc->Init.Mode)); + assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState)); + + /* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the + receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */ + CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /*---------------------------- USART CR2 Configuration ---------------------*/ + tmpreg = hsc->Instance->CR2; + /* Clear CLKEN, CPOL, CPHA and LBCL bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL)); + /* Configure the SMARTCARD Clock, CPOL, CPHA and LastBit -----------------------*/ + /* Set CPOL bit according to hsc->Init.CLKPolarity value */ + /* Set CPHA bit according to hsc->Init.CLKPhase value */ + /* Set LBCL bit according to hsc->Init.CLKLastBit value */ + /* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */ + tmpreg |= (uint32_t)(USART_CR2_CLKEN | hsc->Init.CLKPolarity | + hsc->Init.CLKPhase| hsc->Init.CLKLastBit | hsc->Init.StopBits); + /* Write to USART CR2 */ + WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg); + + tmpreg = hsc->Instance->CR2; + + /* Clear STOP[13:12] bits */ + tmpreg &= (uint32_t)~((uint32_t)USART_CR2_STOP); + + /* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */ + tmpreg |= (uint32_t)(hsc->Init.StopBits); + + /* Write to USART CR2 */ + WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg); + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = hsc->Instance->CR1; + + /* Clear M, PCE, PS, TE and RE bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ + USART_CR1_RE)); + + /* Configure the SMARTCARD Word Length, Parity and mode: + Set the M bits according to hsc->Init.WordLength value + Set PCE and PS bits according to hsc->Init.Parity value + Set TE and RE bits according to hsc->Init.Mode value */ + tmpreg |= (uint32_t)hsc->Init.WordLength | hsc->Init.Parity | hsc->Init.Mode; + + /* Write to USART CR1 */ + WRITE_REG(hsc->Instance->CR1, (uint32_t)tmpreg); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Clear CTSE and RTSE bits */ + CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE)); + + /*-------------------------- USART BRR Configuration -----------------------*/ +#if defined(USART6) + if((hsc->Instance == USART1) || (hsc->Instance == USART6)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate); + } +#else + if(hsc->Instance == USART1) + { + pclk = HAL_RCC_GetPCLK2Freq(); + hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate); + } +#endif /* USART6 */ + else + { + pclk = HAL_RCC_GetPCLK1Freq(); + hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate); + } +} + +/** + * @} + */ + +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c new file mode 100644 index 0000000..84d5d89 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_smbus.c @@ -0,0 +1,2804 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_smbus.c + * @author MCD Application Team + * @brief SMBUS HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the System Management Bus (SMBus) peripheral, + * based on SMBUS principals of operation : + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral State, Mode and Error 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 SMBUS HAL driver can be used as follows: + + (#) Declare a SMBUS_HandleTypeDef handle structure, for example: + SMBUS_HandleTypeDef hsmbus; + + (#)Initialize the SMBUS low level resources by implementing the HAL_SMBUS_MspInit() API: + (##) Enable the SMBUSx interface clock + (##) SMBUS pins configuration + (+++) Enable the clock for the SMBUS GPIOs + (+++) Configure SMBUS pins as alternate function open-drain + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the SMBUSx interrupt priority + (+++) Enable the NVIC SMBUS IRQ Channel + + (#) Configure the Communication Speed, Duty cycle, Addressing mode, Own Address1, + Dual Addressing mode, Own Address2, General call and Nostretch mode in the hsmbus Init structure. + + (#) Initialize the SMBUS registers by calling the HAL_SMBUS_Init(), configures also the low level Hardware + (GPIO, CLOCK, NVIC...etc) by calling the customized HAL_SMBUS_MspInit(&hsmbus) API. + + (#) To check if target device is ready for communication, use the function HAL_SMBUS_IsDeviceReady() + + (#) For SMBUS IO operations, only one mode of operations is available within this driver : + + + *** Interrupt mode IO operation *** + =================================== + + [..] + (+) Transmit in master/host SMBUS mode an amount of data in non blocking mode using HAL_SMBUS_Master_Transmit_IT() + (++) At transmission end of transfer HAL_SMBUS_MasterTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_MasterTxCpltCallback() + (+) Receive in master/host SMBUS mode an amount of data in non blocking mode using HAL_SMBUS_Master_Receive_IT() + (++) At reception end of transfer HAL_SMBUS_MasterRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_MasterRxCpltCallback() + (+) Abort a master/Host SMBUS process communication with Interrupt using HAL_SMBUS_Master_Abort_IT() + (++) End of abort process, HAL_SMBUS_AbortCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_AbortCpltCallback() + (+) Enable/disable the Address listen mode in slave/device or host/slave SMBUS mode + using HAL_SMBUS_EnableListen_IT() HAL_SMBUS_DisableListen_IT() + (++) When address slave/device SMBUS match, HAL_SMBUS_AddrCallback() is executed and user can + add his own code to check the Address Match Code and the transmission direction request by master/host (Write/Read). + (++) At Listen mode end HAL_SMBUS_ListenCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_ListenCpltCallback() + (+) Transmit in slave/device SMBUS mode an amount of data in non blocking mode using HAL_SMBUS_Slave_Transmit_IT() + (++) At transmission end of transfer HAL_SMBUS_SlaveTxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_SlaveTxCpltCallback() + (+) Receive in slave/device SMBUS mode an amount of data in non blocking mode using HAL_SMBUS_Slave_Receive_IT() + (++) At reception end of transfer HAL_SMBUS_SlaveRxCpltCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_SlaveRxCpltCallback() + (+) Enable/Disable the SMBUS alert mode using HAL_SMBUS_EnableAlert_IT() and HAL_SMBUS_DisableAlert_IT() + (++) When SMBUS Alert is generated HAL_SMBUS_ErrorCallback() is executed and user can + add his own code by customization of function pointer HAL_SMBUS_ErrorCallback() + to check the Alert Error Code using function HAL_SMBUS_GetError() + (+) Get HAL state machine or error values using HAL_SMBUS_GetState() or HAL_SMBUS_GetError() + (+) In case of transfer Error, HAL_SMBUS_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SMBUS_ErrorCallback() + to check the Error Code using function HAL_SMBUS_GetError() + + + *** SMBUS HAL driver macros list *** + ================================== + [..] + Below the list of most used macros in SMBUS HAL driver. + + (+) __HAL_SMBUS_ENABLE : Enable the SMBUS peripheral + (+) __HAL_SMBUS_DISABLE : Disable the SMBUS peripheral + (+) __HAL_SMBUS_GET_FLAG : Checks whether the specified SMBUS flag is set or not + (+) __HAL_SMBUS_CLEAR_FLAG: Clear the specified SMBUS pending flag + (+) __HAL_SMBUS_ENABLE_IT : Enable the specified SMBUS interrupt + (+) __HAL_SMBUS_DISABLE_IT: Disable the specified SMBUS interrupt + + [..] + (@) You can refer to the SMBUS HAL driver header file for more useful macros + + *** Callback registration *** + ============================================= + [..] + The compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_SMBUS_RegisterCallback() or HAL_SMBUS_RegisterXXXCallback() + to register an interrupt callback. + + Function HAL_SMBUS_RegisterCallback() allows to register following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + [..] + For specific callback AddrCallback use dedicated register callbacks : HAL_SMBUS_RegisterAddrCallback(). + [..] + Use function HAL_SMBUS_UnRegisterCallback to reset a callback to the default + weak function. + HAL_SMBUS_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) MasterTxCpltCallback : callback for Master transmission end of transfer. + (+) MasterRxCpltCallback : callback for Master reception end of transfer. + (+) SlaveTxCpltCallback : callback for Slave transmission end of transfer. + (+) SlaveRxCpltCallback : callback for Slave reception end of transfer. + (+) ListenCpltCallback : callback for end of listen mode. + (+) ErrorCallback : callback for error detection. + (+) AbortCpltCallback : callback for abort completion process. + (+) MspInitCallback : callback for Msp Init. + (+) MspDeInitCallback : callback for Msp DeInit. + [..] + For callback AddrCallback use dedicated register callbacks : HAL_SMBUS_UnRegisterAddrCallback(). + [..] + By default, after the HAL_SMBUS_Init() and when the state is HAL_SMBUS_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_SMBUS_MasterTxCpltCallback(), HAL_SMBUS_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_SMBUS_Init()/ HAL_SMBUS_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + [..] + Callbacks can be registered/unregistered in HAL_SMBUS_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_SMBUS_STATE_READY or HAL_SMBUS_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_SMBUS_RegisterCallback() before calling HAL_SMBUS_DeInit() + or HAL_SMBUS_Init() function. + [..] + When the compilation flag USE_HAL_SMBUS_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SMBUS SMBUS + * @brief SMBUS HAL module driver + * @{ + */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup SMBUS_Private_Define + * @{ + */ +#define SMBUS_TIMEOUT_FLAG 35U /*!< Timeout 35 ms */ +#define SMBUS_TIMEOUT_BUSY_FLAG 25U /*!< Timeout 25 ms */ +#define SMBUS_NO_OPTION_FRAME 0xFFFF0000U /*!< XferOptions default value */ + +#define SMBUS_SENDPEC_MODE I2C_CR1_PEC +#define SMBUS_GET_PEC(__HANDLE__) (((__HANDLE__)->Instance->SR2 & I2C_SR2_PEC) >> 8) + +/* Private define for @ref PreviousState usage */ +#define SMBUS_STATE_MSK ((uint32_t)((HAL_SMBUS_STATE_BUSY_TX | HAL_SMBUS_STATE_BUSY_RX) & (~(uint32_t)HAL_SMBUS_STATE_READY))) /*!< Mask State define, keep only RX and TX bits */ +#define SMBUS_STATE_NONE ((uint32_t)(HAL_SMBUS_MODE_NONE)) /*!< Default Value */ +#define SMBUS_STATE_MASTER_BUSY_TX ((uint32_t)((HAL_SMBUS_STATE_BUSY_TX & SMBUS_STATE_MSK) | HAL_SMBUS_MODE_MASTER)) /*!< Master Busy TX, combinaison of State LSB and Mode enum */ +#define SMBUS_STATE_MASTER_BUSY_RX ((uint32_t)((HAL_SMBUS_STATE_BUSY_RX & SMBUS_STATE_MSK) | HAL_SMBUS_MODE_MASTER)) /*!< Master Busy RX, combinaison of State LSB and Mode enum */ +#define SMBUS_STATE_SLAVE_BUSY_TX ((uint32_t)((HAL_SMBUS_STATE_BUSY_TX & SMBUS_STATE_MSK) | HAL_SMBUS_MODE_SLAVE)) /*!< Slave Busy TX, combinaison of State LSB and Mode enum */ +#define SMBUS_STATE_SLAVE_BUSY_RX ((uint32_t)((HAL_SMBUS_STATE_BUSY_RX & SMBUS_STATE_MSK) | HAL_SMBUS_MODE_SLAVE)) /*!< Slave Busy RX, combinaison of State LSB and Mode enum */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/** @addtogroup SMBUS_Private_Functions + * @{ + */ + +static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart); +static void SMBUS_ITError(SMBUS_HandleTypeDef *hsmbus); +static void SMBUS_Flush_DR(SMBUS_HandleTypeDef *hsmbus); + +/* Private functions for SMBUS transfer IRQ handler */ +static HAL_StatusTypeDef SMBUS_MasterTransmit_TXE(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_MasterTransmit_BTF(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_MasterReceive_RXNE(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_MasterReceive_BTF(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Master_SB(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Master_ADD10(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Master_ADDR(SMBUS_HandleTypeDef *hsmbus); + +static HAL_StatusTypeDef SMBUS_SlaveTransmit_TXE(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_SlaveTransmit_BTF(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_SlaveReceive_RXNE(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_SlaveReceive_BTF(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Slave_ADDR(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Slave_STOPF(SMBUS_HandleTypeDef *hsmbus); +static HAL_StatusTypeDef SMBUS_Slave_AF(SMBUS_HandleTypeDef *hsmbus); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SMBUS_Exported_Functions SMBUS Exported Functions + * @{ + */ + +/** @defgroup SMBUS_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the SMBUSx peripheral: + + (+) User must Implement HAL_SMBUS_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, IT and NVIC). + + (+) Call the function HAL_SMBUS_Init() to configure the selected device with + the selected configuration: + (++) Communication Speed + (++) Addressing mode + (++) Own Address 1 + (++) Dual Addressing mode + (++) Own Address 2 + (++) General call mode + (++) Nostretch mode + (++) Packet Error Check mode + (++) Peripheral mode + + (+) Call the function HAL_SMBUS_DeInit() to restore the default configuration + of the selected SMBUSx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the SMBUS according to the specified parameters + * in the SMBUS_InitTypeDef and initialize the associated handle. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Init(SMBUS_HandleTypeDef *hsmbus) +{ + uint32_t freqrange = 0U; + uint32_t pclk1 = 0U; + + /* Check the SMBUS handle allocation */ + if (hsmbus == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance)); +#if defined(I2C_FLTR_ANOFF) + assert_param(IS_SMBUS_ANALOG_FILTER(hsmbus->Init.AnalogFilter)); +#endif + assert_param(IS_SMBUS_CLOCK_SPEED(hsmbus->Init.ClockSpeed)); + assert_param(IS_SMBUS_OWN_ADDRESS1(hsmbus->Init.OwnAddress1)); + assert_param(IS_SMBUS_ADDRESSING_MODE(hsmbus->Init.AddressingMode)); + assert_param(IS_SMBUS_DUAL_ADDRESS(hsmbus->Init.DualAddressMode)); + assert_param(IS_SMBUS_OWN_ADDRESS2(hsmbus->Init.OwnAddress2)); + assert_param(IS_SMBUS_GENERAL_CALL(hsmbus->Init.GeneralCallMode)); + assert_param(IS_SMBUS_NO_STRETCH(hsmbus->Init.NoStretchMode)); + assert_param(IS_SMBUS_PEC(hsmbus->Init.PacketErrorCheckMode)); + assert_param(IS_SMBUS_PERIPHERAL_MODE(hsmbus->Init.PeripheralMode)); + + if (hsmbus->State == HAL_SMBUS_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsmbus->Lock = HAL_UNLOCKED; + /* Init the low level hardware : GPIO, CLOCK, NVIC */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + /* Init the SMBUS Callback settings */ + hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback; /* Legacy weak ErrorCallback */ + hsmbus->AbortCpltCallback = HAL_SMBUS_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback */ + + if (hsmbus->MspInitCallback == NULL) + { + hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + hsmbus->MspInitCallback(hsmbus); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC */ + HAL_SMBUS_MspInit(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + + hsmbus->State = HAL_SMBUS_STATE_BUSY; + + /* Disable the selected SMBUS peripheral */ + __HAL_SMBUS_DISABLE(hsmbus); + + /* Get PCLK1 frequency */ + pclk1 = HAL_RCC_GetPCLK1Freq(); + + /* Calculate frequency range */ + freqrange = SMBUS_FREQRANGE(pclk1); + + /*---------------------------- SMBUSx CR2 Configuration ----------------------*/ + /* Configure SMBUSx: Frequency range */ + MODIFY_REG(hsmbus->Instance->CR2, I2C_CR2_FREQ, freqrange); + + /*---------------------------- SMBUSx TRISE Configuration --------------------*/ + /* Configure SMBUSx: Rise Time */ + MODIFY_REG(hsmbus->Instance->TRISE, I2C_TRISE_TRISE, SMBUS_RISE_TIME(freqrange)); + + /*---------------------------- SMBUSx CCR Configuration ----------------------*/ + /* Configure SMBUSx: Speed */ + MODIFY_REG(hsmbus->Instance->CCR, (I2C_CCR_FS | I2C_CCR_DUTY | I2C_CCR_CCR), SMBUS_SPEED_STANDARD(pclk1, hsmbus->Init.ClockSpeed)); + + /*---------------------------- SMBUSx CR1 Configuration ----------------------*/ + /* Configure SMBUSx: Generalcall , PEC , Peripheral mode and NoStretch mode */ + MODIFY_REG(hsmbus->Instance->CR1, (I2C_CR1_NOSTRETCH | I2C_CR1_ENGC | I2C_CR1_ENPEC | I2C_CR1_ENARP | I2C_CR1_SMBTYPE | I2C_CR1_SMBUS), (hsmbus->Init.NoStretchMode | hsmbus->Init.GeneralCallMode | hsmbus->Init.PacketErrorCheckMode | hsmbus->Init.PeripheralMode)); + + /*---------------------------- SMBUSx OAR1 Configuration ---------------------*/ + /* Configure SMBUSx: Own Address1 and addressing mode */ + MODIFY_REG(hsmbus->Instance->OAR1, (I2C_OAR1_ADDMODE | I2C_OAR1_ADD8_9 | I2C_OAR1_ADD1_7 | I2C_OAR1_ADD0), (hsmbus->Init.AddressingMode | hsmbus->Init.OwnAddress1)); + + /*---------------------------- SMBUSx OAR2 Configuration ---------------------*/ + /* Configure SMBUSx: Dual mode and Own Address2 */ + MODIFY_REG(hsmbus->Instance->OAR2, (I2C_OAR2_ENDUAL | I2C_OAR2_ADD2), (hsmbus->Init.DualAddressMode | hsmbus->Init.OwnAddress2)); +#if defined(I2C_FLTR_ANOFF) + /*---------------------------- SMBUSx FLTR Configuration ------------------------*/ + /* Configure SMBUSx: Analog noise filter */ + SET_BIT(hsmbus->Instance->FLTR, hsmbus->Init.AnalogFilter); +#endif + + /* Enable the selected SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + hsmbus->XferPEC = 0x00; + + return HAL_OK; +} + +/** + * @brief DeInitializes the SMBUS peripheral. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_DeInit(SMBUS_HandleTypeDef *hsmbus) +{ + /* Check the SMBUS handle allocation */ + if (hsmbus == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance)); + + hsmbus->State = HAL_SMBUS_STATE_BUSY; + + /* Disable the SMBUS Peripheral Clock */ + __HAL_SMBUS_DISABLE(hsmbus); + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + if (hsmbus->MspDeInitCallback == NULL) + { + hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + hsmbus->MspDeInitCallback(hsmbus); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC */ + HAL_SMBUS_MspDeInit(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->State = HAL_SMBUS_STATE_RESET; + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + + /* Release Lock */ + __HAL_UNLOCK(hsmbus); + + return HAL_OK; +} + +/** + * @brief Initialize the SMBUS MSP. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS + * @retval None + */ +__weak void HAL_SMBUS_MspInit(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SMBUS_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitialize the SMBUS MSP. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS + * @retval None + */ +__weak void HAL_SMBUS_MspDeInit(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SMBUS_MspDeInit could be implemented in the user file + */ +} + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +/** + * @brief Configures SMBUS Analog noise filter. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUSx peripheral. + * @param AnalogFilter new state of the Analog filter. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_ConfigAnalogFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t AnalogFilter) +{ + /* Check the parameters */ + assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance)); + assert_param(IS_SMBUS_ANALOG_FILTER(AnalogFilter)); + + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + hsmbus->State = HAL_SMBUS_STATE_BUSY; + + /* Disable the selected SMBUS peripheral */ + __HAL_SMBUS_DISABLE(hsmbus); + + /* Reset SMBUSx ANOFF bit */ + hsmbus->Instance->FLTR &= ~(I2C_FLTR_ANOFF); + + /* Disable the analog filter */ + hsmbus->Instance->FLTR |= AnalogFilter; + + __HAL_SMBUS_ENABLE(hsmbus); + + hsmbus->State = HAL_SMBUS_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures SMBUS Digital noise filter. + * @param hsmbus pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUSx peripheral. + * @param DigitalFilter Coefficient of digital noise filter between 0x00 and 0x0F. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_ConfigDigitalFilter(SMBUS_HandleTypeDef *hsmbus, uint32_t DigitalFilter) +{ + uint16_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SMBUS_ALL_INSTANCE(hsmbus->Instance)); + assert_param(IS_SMBUS_DIGITAL_FILTER(DigitalFilter)); + + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + hsmbus->State = HAL_SMBUS_STATE_BUSY; + + /* Disable the selected SMBUS peripheral */ + __HAL_SMBUS_DISABLE(hsmbus); + + /* Get the old register value */ + tmpreg = hsmbus->Instance->FLTR; + + /* Reset SMBUSx DNF bit [3:0] */ + tmpreg &= ~(I2C_FLTR_DNF); + + /* Set SMBUSx DNF coefficient */ + tmpreg |= DigitalFilter; + + /* Store the new register value */ + hsmbus->Instance->FLTR = tmpreg; + + __HAL_SMBUS_ENABLE(hsmbus); + + hsmbus->State = HAL_SMBUS_STATE_READY; + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +#endif +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User SMBUS Callback + * To be used instead of the weak predefined callback + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID + * @arg @ref HAL_SMBUS_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_RegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID, pSMBUS_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hsmbus); + + if (HAL_SMBUS_STATE_READY == hsmbus->State) + { + switch (CallbackID) + { + case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID : + hsmbus->MasterTxCpltCallback = pCallback; + break; + + case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID : + hsmbus->MasterRxCpltCallback = pCallback; + break; + + case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID : + hsmbus->SlaveTxCpltCallback = pCallback; + break; + + case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID : + hsmbus->SlaveRxCpltCallback = pCallback; + break; + + case HAL_SMBUS_LISTEN_COMPLETE_CB_ID : + hsmbus->ListenCpltCallback = pCallback; + break; + + case HAL_SMBUS_ERROR_CB_ID : + hsmbus->ErrorCallback = pCallback; + break; + + case HAL_SMBUS_ABORT_CB_ID : + hsmbus->AbortCpltCallback = pCallback; + break; + + case HAL_SMBUS_MSPINIT_CB_ID : + hsmbus->MspInitCallback = pCallback; + break; + + case HAL_SMBUS_MSPDEINIT_CB_ID : + hsmbus->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SMBUS_STATE_RESET == hsmbus->State) + { + switch (CallbackID) + { + case HAL_SMBUS_MSPINIT_CB_ID : + hsmbus->MspInitCallback = pCallback; + break; + + case HAL_SMBUS_MSPDEINIT_CB_ID : + hsmbus->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsmbus); + return status; +} + +/** + * @brief Unregister an SMBUS Callback + * SMBUS callback is redirected to the weak predefined callback + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * This parameter can be one of the following values: + * @arg @ref HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID Master Tx Transfer completed callback ID + * @arg @ref HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID Master Rx Transfer completed callback ID + * @arg @ref HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID Slave Tx Transfer completed callback ID + * @arg @ref HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID Slave Rx Transfer completed callback ID + * @arg @ref HAL_SMBUS_LISTEN_COMPLETE_CB_ID Listen Complete callback ID + * @arg @ref HAL_SMBUS_ERROR_CB_ID Error callback ID + * @arg @ref HAL_SMBUS_ABORT_CB_ID Abort callback ID + * @arg @ref HAL_SMBUS_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_SMBUS_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_UnRegisterCallback(SMBUS_HandleTypeDef *hsmbus, HAL_SMBUS_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hsmbus); + + if (HAL_SMBUS_STATE_READY == hsmbus->State) + { + switch (CallbackID) + { + case HAL_SMBUS_MASTER_TX_COMPLETE_CB_ID : + hsmbus->MasterTxCpltCallback = HAL_SMBUS_MasterTxCpltCallback; /* Legacy weak MasterTxCpltCallback */ + break; + + case HAL_SMBUS_MASTER_RX_COMPLETE_CB_ID : + hsmbus->MasterRxCpltCallback = HAL_SMBUS_MasterRxCpltCallback; /* Legacy weak MasterRxCpltCallback */ + break; + + case HAL_SMBUS_SLAVE_TX_COMPLETE_CB_ID : + hsmbus->SlaveTxCpltCallback = HAL_SMBUS_SlaveTxCpltCallback; /* Legacy weak SlaveTxCpltCallback */ + break; + + case HAL_SMBUS_SLAVE_RX_COMPLETE_CB_ID : + hsmbus->SlaveRxCpltCallback = HAL_SMBUS_SlaveRxCpltCallback; /* Legacy weak SlaveRxCpltCallback */ + break; + + case HAL_SMBUS_LISTEN_COMPLETE_CB_ID : + hsmbus->ListenCpltCallback = HAL_SMBUS_ListenCpltCallback; /* Legacy weak ListenCpltCallback */ + break; + + case HAL_SMBUS_ERROR_CB_ID : + hsmbus->ErrorCallback = HAL_SMBUS_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_SMBUS_ABORT_CB_ID : + hsmbus->AbortCpltCallback = HAL_SMBUS_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_SMBUS_MSPINIT_CB_ID : + hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SMBUS_MSPDEINIT_CB_ID : + hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SMBUS_STATE_RESET == hsmbus->State) + { + switch (CallbackID) + { + case HAL_SMBUS_MSPINIT_CB_ID : + hsmbus->MspInitCallback = HAL_SMBUS_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SMBUS_MSPDEINIT_CB_ID : + hsmbus->MspDeInitCallback = HAL_SMBUS_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsmbus); + return status; +} + +/** + * @brief Register the Slave Address Match SMBUS Callback + * To be used instead of the weak HAL_SMBUS_AddrCallback() predefined callback + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param pCallback pointer to the Address Match Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_RegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus, pSMBUS_AddrCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hsmbus); + + if (HAL_SMBUS_STATE_READY == hsmbus->State) + { + hsmbus->AddrCallback = pCallback; + } + else + { + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsmbus); + return status; +} + +/** + * @brief UnRegister the Slave Address Match SMBUS Callback + * Info Ready SMBUS Callback is redirected to the weak HAL_SMBUS_AddrCallback() predefined callback + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_UnRegisterAddrCallback(SMBUS_HandleTypeDef *hsmbus) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hsmbus); + + if (HAL_SMBUS_STATE_READY == hsmbus->State) + { + hsmbus->AddrCallback = HAL_SMBUS_AddrCallback; /* Legacy weak AddrCallback */ + } + else + { + /* Update the error code */ + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsmbus); + return status; +} + +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + +/** + * @brief SMBUS data register flush process. + * @param hsmbus SMBUS handle. + * @retval None + */ +static void SMBUS_Flush_DR(SMBUS_HandleTypeDef *hsmbus) +{ + /* Write a dummy data in DR to clear it */ + hsmbus->Instance->DR = 0x00U; + +} + +/** + * @} + */ + +/** @defgroup SMBUS_Exported_Functions_Group2 Input and Output operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SMBUS data + transfers. + + (#) Blocking mode function to check if device is ready for usage is : + (++) HAL_SMBUS_IsDeviceReady() + + (#) There is only one mode of transfer: + (++) Non Blocking mode : The communication is performed using Interrupts. + These functions return the status of the transfer startup. + The end of the data processing will be indicated through the + dedicated SMBUS IRQ when using Interrupt mode. + + (#) Non Blocking mode functions with Interrupt are : + (++) HAL_SMBUS_Master_Transmit_IT() + (++) HAL_SMBUS_Master_Receive_IT() + (++) HAL_SMBUS_Master_Abort_IT() + (++) HAL_SMBUS_Slave_Transmit_IT() + (++) HAL_SMBUS_Slave_Receive_IT() + (++) HAL_SMBUS_EnableAlert_IT() + (++) HAL_SMBUS_DisableAlert_IT() + + (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode: + (++) HAL_SMBUS_MasterTxCpltCallback() + (++) HAL_SMBUS_MasterRxCpltCallback() + (++) HAL_SMBUS_SlaveTxCpltCallback() + (++) HAL_SMBUS_SlaveRxCpltCallback() + (++) HAL_SMBUS_AddrCallback() + (++) HAL_SMBUS_ListenCpltCallback() + (++) HAL_SMBUS_ErrorCallback() + (++) HAL_SMBUS_AbortCpltCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Master_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + uint32_t count = 0x00U; + + /* Check the parameters */ + assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((XferOptions == SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || (XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (XferOptions == SMBUS_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = SMBUS_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + if (count-- == 0U) + { + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + return HAL_TIMEOUT; + } + } + while (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hsmbus); + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Disable Pos */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + hsmbus->State = HAL_SMBUS_STATE_BUSY_TX; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_MASTER; + + /* Prepare transfer parameters */ + hsmbus->pBuffPtr = pData; + hsmbus->XferCount = Size; + hsmbus->XferOptions = XferOptions; + hsmbus->XferSize = hsmbus->XferCount; + hsmbus->Devaddress = DevAddress; + + /* Generate Start */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + /* Note : The SMBUS interrupts must be enabled after unlocking current process + to avoid the risk of hsmbus interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} +/** + * @brief Receive in master/host SMBUS mode an amount of data in non blocking mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Master_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + __IO uint32_t count = 0U; + + /* Check the parameters */ + assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + /* Check Busy Flag only if FIRST call of Master interface */ + if ((XferOptions == SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || (XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (XferOptions == SMBUS_FIRST_FRAME)) + { + /* Wait until BUSY flag is reset */ + count = SMBUS_TIMEOUT_BUSY_FLAG * (SystemCoreClock / 25U / 1000U); + do + { + if (count-- == 0U) + { + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + return HAL_TIMEOUT; + } + } + while (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BUSY) != RESET); + } + + /* Process Locked */ + __HAL_LOCK(hsmbus); + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Disable Pos */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + hsmbus->State = HAL_SMBUS_STATE_BUSY_RX; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_MASTER; + + /* Prepare transfer parameters */ + hsmbus->pBuffPtr = pData; + hsmbus->XferCount = Size; + hsmbus->XferOptions = XferOptions; + hsmbus->XferSize = hsmbus->XferCount; + hsmbus->Devaddress = DevAddress; + + if ((hsmbus->PreviousState == SMBUS_STATE_MASTER_BUSY_TX) || (hsmbus->PreviousState == SMBUS_STATE_NONE)) + { + /* Generate Start condition if first transfer */ + if ((XferOptions == SMBUS_NEXT_FRAME) || (XferOptions == SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || (XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (XferOptions == SMBUS_FIRST_FRAME) || (XferOptions == SMBUS_NO_OPTION_FRAME)) + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + } + + if ((XferOptions == SMBUS_LAST_FRAME_NO_PEC) || (XferOptions == SMBUS_LAST_FRAME_WITH_PEC)) + { + if (hsmbus->PreviousState == SMBUS_STATE_NONE) + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + } + + if (hsmbus->PreviousState == SMBUS_STATE_MASTER_BUSY_TX) + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Generate Start */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + } + } + } + + + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + /* Note : The SMBUS interrupts must be enabled after unlocking current process + to avoid the risk of SMBUS interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Abort a master/host SMBUS process communication with Interrupt. + * @note This abort can be called only if state is ready + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Master_Abort_IT(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(DevAddress); + if (hsmbus->Init.PeripheralMode == SMBUS_PERIPHERAL_MODE_SMBUS_HOST) + { + /* Process Locked */ + __HAL_LOCK(hsmbus); + + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_ABORT; + + + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + hsmbus->XferCount = 0U; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ + SMBUS_ITError(hsmbus); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + + +/** + * @brief Transmit in slave/device SMBUS mode an amount of data in non blocking mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Slave_Transmit_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hsmbus->State == HAL_SMBUS_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsmbus); + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Disable Pos */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + hsmbus->State = HAL_SMBUS_STATE_BUSY_TX_LISTEN; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_SLAVE; + + /* Prepare transfer parameters */ + hsmbus->pBuffPtr = pData; + hsmbus->XferCount = Size; + hsmbus->XferOptions = XferOptions; + hsmbus->XferSize = hsmbus->XferCount; + + /* Clear ADDR flag after prepare the transfer parameters */ + /* This action will generate an acknowledge to the HOST */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + /* Note : The SMBUS interrupts must be enabled after unlocking current process + to avoid the risk of SMBUS interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param pData Pointer to data buffer + * @param Size Amount of data to be sent + * @param XferOptions Options of Transfer, value of @ref SMBUS_XferOptions_definition + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_Slave_Receive_IT(SMBUS_HandleTypeDef *hsmbus, uint8_t *pData, uint16_t Size, uint32_t XferOptions) +{ + /* Check the parameters */ + assert_param(IS_SMBUS_TRANSFER_OPTIONS_REQUEST(XferOptions)); + + if (hsmbus->State == HAL_SMBUS_STATE_LISTEN) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hsmbus); + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Disable Pos */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + hsmbus->State = HAL_SMBUS_STATE_BUSY_RX_LISTEN; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_SLAVE; + + + + /* Prepare transfer parameters */ + hsmbus->pBuffPtr = pData; + hsmbus->XferCount = Size; + hsmbus->XferOptions = XferOptions; + hsmbus->XferSize = hsmbus->XferCount; + + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + /* Note : The SMBUS interrupts must be enabled after unlocking current process + to avoid the risk of SMBUS interrupt handle execution before current + process unlock */ + + /* Enable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + + +/** + * @brief Enable the Address listen mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_EnableListen_IT(SMBUS_HandleTypeDef *hsmbus) +{ + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + hsmbus->State = HAL_SMBUS_STATE_LISTEN; + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Enable Address Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Enable EVT and ERR interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Disable the Address listen mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_DisableListen_IT(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of tmp to prevent undefined behavior of volatile usage */ + uint32_t tmp; + + /* Disable Address listen mode only if a transfer is not ongoing */ + if (hsmbus->State == HAL_SMBUS_STATE_LISTEN) + { + tmp = (uint32_t)(hsmbus->State) & SMBUS_STATE_MSK; + hsmbus->PreviousState = tmp | (uint32_t)(hsmbus->Mode); + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + + /* Disable Address Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Disable EVT and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_ERR); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Enable the SMBUS alert mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUSx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_EnableAlert_IT(SMBUS_HandleTypeDef *hsmbus) +{ + /* Enable SMBus alert */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ALERT); + + /* Clear ALERT flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_SMBALERT); + + /* Enable Alert Interrupt */ + __HAL_SMBUS_ENABLE_IT(hsmbus, SMBUS_IT_ERR); + + return HAL_OK; +} +/** + * @brief Disable the SMBUS alert mode with Interrupt. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUSx peripheral. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_DisableAlert_IT(SMBUS_HandleTypeDef *hsmbus) +{ + /* Disable SMBus alert */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ALERT); + + /* Disable Alert Interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_ERR); + + return HAL_OK; +} + + +/** + * @brief Check if target device is ready for communication. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param DevAddress Target device address The device 7 bits address value + * in datasheet must be shifted to the left before calling the interface + * @param Trials Number of trials + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SMBUS_IsDeviceReady(SMBUS_HandleTypeDef *hsmbus, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout) +{ + uint32_t tickstart = 0U, tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, SMBUS_Trials = 1U; + + /* Get tick */ + tickstart = HAL_GetTick(); + + if (hsmbus->State == HAL_SMBUS_STATE_READY) + { + /* Wait until BUSY flag is reset */ + if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_BUSY, SET, SMBUS_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_BUSY; + } + + /* Process Locked */ + __HAL_LOCK(hsmbus); + + /* Check if the SMBUS is already enabled */ + if ((hsmbus->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) + { + /* Enable SMBUS peripheral */ + __HAL_SMBUS_ENABLE(hsmbus); + } + + /* Disable Pos */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + hsmbus->State = HAL_SMBUS_STATE_BUSY; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + hsmbus->XferOptions = SMBUS_NO_OPTION_FRAME; + + do + { + /* Generate Start */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + + /* Wait until SB flag is set */ + if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_SB, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Send slave address */ + hsmbus->Instance->DR = SMBUS_7BIT_ADD_WRITE(DevAddress); + + /* Wait until ADDR or AF flag are set */ + /* Get tick */ + tickstart = HAL_GetTick(); + + tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_ADDR); + tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF); + tmp3 = hsmbus->State; + while ((tmp1 == RESET) && (tmp2 == RESET) && (tmp3 != HAL_SMBUS_STATE_TIMEOUT)) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + hsmbus->State = HAL_SMBUS_STATE_TIMEOUT; + } + tmp1 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_ADDR); + tmp2 = __HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_AF); + tmp3 = hsmbus->State; + } + + hsmbus->State = HAL_SMBUS_STATE_READY; + + /* Check if the ADDR flag has been set */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_ADDR) == SET) + { + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + /* Clear ADDR Flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Wait until BUSY flag is reset */ + if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_BUSY, SET, SMBUS_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + hsmbus->State = HAL_SMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + return HAL_OK; + } + else + { + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + /* Clear AF Flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF); + + /* Wait until BUSY flag is reset */ + if (SMBUS_WaitOnFlagUntilTimeout(hsmbus, SMBUS_FLAG_BUSY, SET, SMBUS_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + } + } + while (SMBUS_Trials++ < Trials); + + hsmbus->State = HAL_SMBUS_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + + return HAL_ERROR; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief This function handles SMBUS event interrupt request. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +void HAL_SMBUS_EV_IRQHandler(SMBUS_HandleTypeDef *hsmbus) +{ + uint32_t sr2itflags = READ_REG(hsmbus->Instance->SR2); + uint32_t sr1itflags = READ_REG(hsmbus->Instance->SR1); + uint32_t itsources = READ_REG(hsmbus->Instance->CR2); + + uint32_t CurrentMode = hsmbus->Mode; + + /* Master mode selected */ + if (CurrentMode == HAL_SMBUS_MODE_MASTER) + { + /* SB Set ----------------------------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_SB) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_Master_SB(hsmbus); + } + /* ADD10 Set -------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_ADD10) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_Master_ADD10(hsmbus); + } + /* ADDR Set --------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_ADDR) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_Master_ADDR(hsmbus); + } + /* SMBUS in mode Transmitter -----------------------------------------------*/ + if ((sr2itflags & SMBUS_FLAG_TRA) != RESET) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_TXE) != RESET) && ((itsources & SMBUS_IT_BUF) != RESET) && ((sr1itflags & SMBUS_FLAG_BTF) == RESET)) + { + SMBUS_MasterTransmit_TXE(hsmbus); + } + /* BTF set -------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_BTF) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_MasterTransmit_BTF(hsmbus); + } + } + /* SMBUS in mode Receiver --------------------------------------------------*/ + else + { + /* RXNE set and BTF reset -----------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_RXNE) != RESET) && ((itsources & SMBUS_IT_BUF) != RESET) && ((sr1itflags & SMBUS_FLAG_BTF) == RESET)) + { + SMBUS_MasterReceive_RXNE(hsmbus); + } + /* BTF set -------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_BTF) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_MasterReceive_BTF(hsmbus); + } + } + } + /* Slave mode selected */ + else + { + /* ADDR set --------------------------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_ADDR) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_Slave_ADDR(hsmbus); + } + /* STOPF set --------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_STOPF) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_Slave_STOPF(hsmbus); + } + /* SMBUS in mode Transmitter -----------------------------------------------*/ + else if ((sr2itflags & SMBUS_FLAG_TRA) != RESET) + { + /* TXE set and BTF reset -----------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_TXE) != RESET) && ((itsources & SMBUS_IT_BUF) != RESET) && ((sr1itflags & SMBUS_FLAG_BTF) == RESET)) + { + SMBUS_SlaveTransmit_TXE(hsmbus); + } + /* BTF set -------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_BTF) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_SlaveTransmit_BTF(hsmbus); + } + } + /* SMBUS in mode Receiver --------------------------------------------------*/ + else + { + /* RXNE set and BTF reset ----------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_RXNE) != RESET) && ((itsources & SMBUS_IT_BUF) != RESET) && ((sr1itflags & SMBUS_FLAG_BTF) == RESET)) + { + SMBUS_SlaveReceive_RXNE(hsmbus); + } + /* BTF set -------------------------------------------------------------*/ + else if (((sr1itflags & SMBUS_FLAG_BTF) != RESET) && ((itsources & SMBUS_IT_EVT) != RESET)) + { + SMBUS_SlaveReceive_BTF(hsmbus); + } + } + } +} + +/** + * @brief This function handles SMBUS error interrupt request. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +void HAL_SMBUS_ER_IRQHandler(SMBUS_HandleTypeDef *hsmbus) +{ + uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U, tmp4 = 0U; + uint32_t sr1itflags = READ_REG(hsmbus->Instance->SR1); + uint32_t itsources = READ_REG(hsmbus->Instance->CR2); + + /* SMBUS Bus error interrupt occurred ------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_BERR) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_BERR; + + /* Clear BERR flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_BERR); + + } + + /* SMBUS Over-Run/Under-Run interrupt occurred ----------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_OVR) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_OVR; + + /* Clear OVR flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_OVR); + } + + /* SMBUS Arbitration Loss error interrupt occurred ------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_ARLO) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ARLO; + + /* Clear ARLO flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_ARLO); + } + + /* SMBUS Acknowledge failure error interrupt occurred ------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_AF) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + tmp1 = hsmbus->Mode; + tmp2 = hsmbus->XferCount; + tmp3 = hsmbus->State; + tmp4 = hsmbus->PreviousState; + + if ((tmp1 == HAL_SMBUS_MODE_SLAVE) && (tmp2 == 0U) && \ + ((tmp3 == HAL_SMBUS_STATE_BUSY_TX) || (tmp3 == HAL_SMBUS_STATE_BUSY_TX_LISTEN) || \ + ((tmp3 == HAL_SMBUS_STATE_LISTEN) && (tmp4 == SMBUS_STATE_SLAVE_BUSY_TX)))) + { + SMBUS_Slave_AF(hsmbus); + } + else + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_AF; + + /* Do not generate a STOP in case of Slave receive non acknowledge during transfer (mean not at the end of transfer) */ + if (hsmbus->Mode == HAL_SMBUS_MODE_MASTER) + { + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + } + + /* Clear AF flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF); + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Flush data register */ + SMBUS_Flush_DR(hsmbus); + + } + } + + /* SMBUS Timeout error interrupt occurred ---------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_TIMEOUT) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_TIMEOUT; + + /* Clear TIMEOUT flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_TIMEOUT); + + } + + /* SMBUS Alert error interrupt occurred -----------------------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_SMBALERT) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_ALERT; + + /* Clear ALERT flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_SMBALERT); + } + + /* SMBUS Packet Error Check error interrupt occurred ----------------------------------*/ + if (((sr1itflags & SMBUS_FLAG_PECERR) != RESET) && ((itsources & SMBUS_IT_ERR) != RESET)) + { + hsmbus->ErrorCode |= HAL_SMBUS_ERROR_PECERR; + + /* Clear PEC error flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_PECERR); + } + + /* Call the Error Callback in case of Error detected -----------------------*/ + if (hsmbus->ErrorCode != HAL_SMBUS_ERROR_NONE) + { + SMBUS_ITError(hsmbus); + } +} + +/** + * @brief Master Tx Transfer completed callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_MasterTxCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_MasterTxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Master Rx Transfer completed callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_MasterRxCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_MasterRxCpltCallback can be implemented in the user file + */ +} + +/** @brief Slave Tx Transfer completed callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_SlaveTxCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_SlaveTxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Slave Rx Transfer completed callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_SlaveRxCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_SlaveRxCpltCallback can be implemented in the user file + */ +} + +/** + * @brief Slave Address Match callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @param TransferDirection Master request Transfer Direction (Write/Read), value of @ref SMBUS_XferOptions_definition + * @param AddrMatchCode Address Match Code + * @retval None + */ +__weak void HAL_SMBUS_AddrCallback(SMBUS_HandleTypeDef *hsmbus, uint8_t TransferDirection, uint16_t AddrMatchCode) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + UNUSED(TransferDirection); + UNUSED(AddrMatchCode); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_AddrCallback can be implemented in the user file + */ +} + +/** + * @brief Listen Complete callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_ListenCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_ListenCpltCallback can be implemented in the user file + */ +} + +/** + * @brief SMBUS error callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_ErrorCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_ErrorCallback can be implemented in the user file + */ +} + +/** + * @brief SMBUS abort callback. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval None + */ +__weak void HAL_SMBUS_AbortCpltCallback(SMBUS_HandleTypeDef *hsmbus) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsmbus); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SMBUS_AbortCpltCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup SMBUS_Exported_Functions_Group3 Peripheral State, Mode and Error functions + * @brief Peripheral State and Errors functions + * +@verbatim + =============================================================================== + ##### Peripheral State, Mode and Error functions ##### + =============================================================================== + [..] + This subsection permits to get in run-time the status of the peripheral + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the SMBUS handle state. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval HAL state + */ +HAL_SMBUS_StateTypeDef HAL_SMBUS_GetState(SMBUS_HandleTypeDef *hsmbus) +{ + /* Return SMBUS handle state */ + return hsmbus->State; +} + +/** + * @brief Return the SMBUS Master, Slave or no mode. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL mode + */ +HAL_SMBUS_ModeTypeDef HAL_SMBUS_GetMode(SMBUS_HandleTypeDef *hsmbus) +{ + return hsmbus->Mode; +} + +/** + * @brief Return the SMBUS error code + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for the specified SMBUS. + * @retval SMBUS Error Code + */ +uint32_t HAL_SMBUS_GetError(SMBUS_HandleTypeDef *hsmbus) +{ + return hsmbus->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SMBUS_Private_Functions + * @{ + */ + +/** + * @brief Handle TXE flag for Master + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_MasterTransmit_TXE(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + uint32_t CurrentXferOptions = hsmbus->XferOptions; + + if ((hsmbus->XferSize == 0U) && (CurrentState == HAL_SMBUS_STATE_BUSY_TX)) + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if (((CurrentXferOptions == SMBUS_FIRST_FRAME) || (CurrentXferOptions == SMBUS_NEXT_FRAME)) && (CurrentXferOptions != SMBUS_NO_OPTION_FRAME)) + { + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + hsmbus->PreviousState = SMBUS_STATE_MASTER_BUSY_TX; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterTxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterTxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + hsmbus->PreviousState = HAL_SMBUS_STATE_READY; + hsmbus->State = HAL_SMBUS_STATE_READY; + + hsmbus->Mode = HAL_SMBUS_MODE_NONE; +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterTxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterTxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + else if (CurrentState == HAL_SMBUS_STATE_BUSY_TX) + { + + if ((hsmbus->XferCount == 2U) && (SMBUS_GET_PEC_MODE(hsmbus) == SMBUS_PEC_ENABLE) && ((hsmbus->XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (hsmbus->XferOptions == SMBUS_LAST_FRAME_WITH_PEC))) + { + hsmbus->XferCount--; + } + + if (hsmbus->XferCount == 0U) + { + + /* Disable BUF interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + + if ((SMBUS_GET_PEC_MODE(hsmbus) == SMBUS_PEC_ENABLE) && ((hsmbus->XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (hsmbus->XferOptions == SMBUS_LAST_FRAME_WITH_PEC))) + { + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_PEC); + } + + } + else + { + /* Write data to DR */ + hsmbus->Instance->DR = (*hsmbus->pBuffPtr++); + hsmbus->XferCount--; + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Master transmitter + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_MasterTransmit_BTF(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hsmbus->XferOptions; + + if (hsmbus->State == HAL_SMBUS_STATE_BUSY_TX) + { + if (hsmbus->XferCount != 0U) + { + /* Write data to DR */ + hsmbus->Instance->DR = (*hsmbus->pBuffPtr++); + hsmbus->XferCount--; + } + else + { + /* Call TxCpltCallback() directly if no stop mode is set */ + if (((CurrentXferOptions == SMBUS_FIRST_FRAME) || (CurrentXferOptions == SMBUS_NEXT_FRAME)) && (CurrentXferOptions != SMBUS_NO_OPTION_FRAME)) + { + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + hsmbus->PreviousState = SMBUS_STATE_MASTER_BUSY_TX; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterTxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterTxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + else /* Generate Stop condition then Call TxCpltCallback() */ + { + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterTxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterTxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + } + return HAL_OK; +} + +/** + * @brief Handle RXNE flag for Master + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_MasterReceive_RXNE(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hsmbus->XferOptions; + + if (hsmbus->State == HAL_SMBUS_STATE_BUSY_RX) + { + uint32_t tmp = hsmbus->XferCount; + + if (tmp > 3U) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + if (hsmbus->XferCount == 3) + { + /* Disable BUF interrupt, this help to treat correctly the last 4 bytes + on BTF subroutine */ + /* Disable BUF interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + } + } + + else if (tmp == 2U) + { + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + if ((CurrentXferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (CurrentXferOptions == SMBUS_LAST_FRAME_WITH_PEC)) + { + /* PEC of slave */ + hsmbus->XferPEC = SMBUS_GET_PEC(hsmbus); + + } + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + } + + else if ((tmp == 1U) || (tmp == 0U)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterRxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterRxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Master receiver + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_MasterReceive_BTF(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentXferOptions = hsmbus->XferOptions; + + if (hsmbus->XferCount == 4U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + hsmbus->XferPEC = SMBUS_GET_PEC(hsmbus); + } + else if (hsmbus->XferCount == 3U) + { + /* Disable BUF interrupt, this help to treat correctly the last 2 bytes + on BTF subroutine if there is a reception delay between N-1 and N byte */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + hsmbus->XferPEC = SMBUS_GET_PEC(hsmbus); + } + else if (hsmbus->XferCount == 2U) + { + /* Prepare next transfer or stop current transfer */ + if ((CurrentXferOptions == SMBUS_NEXT_FRAME) || (CurrentXferOptions == SMBUS_FIRST_FRAME)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Generate ReStart */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + } + else + { + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + } + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + /* Disable EVT and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_ERR); + + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->MasterRxCpltCallback(hsmbus); +#else + HAL_SMBUS_MasterRxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + } + return HAL_OK; +} + +/** + * @brief Handle SB flag for Master + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Master_SB(SMBUS_HandleTypeDef *hsmbus) +{ + if (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_7BIT) + { + /* Send slave 7 Bits address */ + if (hsmbus->State == HAL_SMBUS_STATE_BUSY_TX) + { + hsmbus->Instance->DR = SMBUS_7BIT_ADD_WRITE(hsmbus->Devaddress); + } + else + { + hsmbus->Instance->DR = SMBUS_7BIT_ADD_READ(hsmbus->Devaddress); + } + } + else + { + if (hsmbus->EventCount == 0U) + { + /* Send header of slave address */ + hsmbus->Instance->DR = SMBUS_10BIT_HEADER_WRITE(hsmbus->Devaddress); + } + else if (hsmbus->EventCount == 1U) + { + /* Send header of slave address */ + hsmbus->Instance->DR = SMBUS_10BIT_HEADER_READ(hsmbus->Devaddress); + } + } + return HAL_OK; +} + +/** + * @brief Handle ADD10 flag for Master + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Master_ADD10(SMBUS_HandleTypeDef *hsmbus) +{ + /* Send slave address */ + hsmbus->Instance->DR = SMBUS_10BIT_ADDRESS(hsmbus->Devaddress); + + return HAL_OK; +} + +/** + * @brief Handle ADDR flag for Master + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Master_ADDR(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t Prev_State = hsmbus->PreviousState; + + if (hsmbus->State == HAL_SMBUS_STATE_BUSY_RX) + { + if ((hsmbus->EventCount == 0U) && (hsmbus->Init.AddressingMode == SMBUS_ADDRESSINGMODE_10BIT)) + { + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Generate Restart */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_START); + + hsmbus->EventCount++; + } + else + { + /* In the case of the Quick Command, the ADDR flag is cleared and a stop is generated */ + if (hsmbus->XferCount == 0U) + { + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + } + else if (hsmbus->XferCount == 1U) + { + /* Prepare next transfer or stop current transfer */ + if ((hsmbus->XferOptions == SMBUS_FIRST_FRAME) && (Prev_State != SMBUS_STATE_MASTER_BUSY_RX)) + { + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + } + else if ((hsmbus->XferOptions == SMBUS_NEXT_FRAME) && (Prev_State != SMBUS_STATE_MASTER_BUSY_RX)) + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + } + else + { + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + + /* Generate Stop */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_STOP); + } + } + else if (hsmbus->XferCount == 2U) + { + if (hsmbus->XferOptions != SMBUS_NEXT_FRAME) + { + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Enable Pos */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + + } + else + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + } + + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + } + else + { + /* Enable Acknowledge */ + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + } + + /* Reset Event counter */ + hsmbus->EventCount = 0U; + } + } + else + { + /* Clear ADDR flag */ + __HAL_SMBUS_CLEAR_ADDRFLAG(hsmbus); + } + + return HAL_OK; +} + +/** + * @brief Handle TXE flag for Slave + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_SlaveTransmit_TXE(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + + if (hsmbus->XferCount != 0U) + { + /* Write data to DR */ + hsmbus->Instance->DR = (*hsmbus->pBuffPtr++); + hsmbus->XferCount--; + + if ((hsmbus->XferCount == 2U) && (SMBUS_GET_PEC_MODE(hsmbus) == SMBUS_PEC_ENABLE) && ((hsmbus->XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (hsmbus->XferOptions == SMBUS_LAST_FRAME_WITH_PEC))) + { + hsmbus->XferCount--; + } + + if ((hsmbus->XferCount == 0U) && (CurrentState == (HAL_SMBUS_STATE_BUSY_TX_LISTEN))) + { + /* Last Byte is received, disable Interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + + /* Set state at HAL_SMBUS_STATE_LISTEN */ + hsmbus->PreviousState = SMBUS_STATE_SLAVE_BUSY_TX; + hsmbus->State = HAL_SMBUS_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->SlaveTxCpltCallback(hsmbus); +#else + HAL_SMBUS_SlaveTxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Slave transmitter + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_SlaveTransmit_BTF(SMBUS_HandleTypeDef *hsmbus) +{ + if (hsmbus->XferCount != 0U) + { + /* Write data to DR */ + hsmbus->Instance->DR = (*hsmbus->pBuffPtr++); + hsmbus->XferCount--; + } + + + + else if ((hsmbus->XferCount == 0U) && (SMBUS_GET_PEC_MODE(hsmbus) == SMBUS_PEC_ENABLE) && ((hsmbus->XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (hsmbus->XferOptions == SMBUS_LAST_FRAME_WITH_PEC))) + { + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_PEC); + } + return HAL_OK; +} + +/** + * @brief Handle RXNE flag for Slave + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_SlaveReceive_RXNE(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + + if (hsmbus->XferCount != 0U) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + + if ((hsmbus->XferCount == 1U) && (SMBUS_GET_PEC_MODE(hsmbus) == SMBUS_PEC_ENABLE) && ((hsmbus->XferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || (hsmbus->XferOptions == SMBUS_LAST_FRAME_WITH_PEC))) + { + SET_BIT(hsmbus->Instance->CR1, I2C_CR1_PEC); + hsmbus->XferPEC = SMBUS_GET_PEC(hsmbus); + } + if ((hsmbus->XferCount == 0U) && (CurrentState == HAL_SMBUS_STATE_BUSY_RX_LISTEN)) + { + /* Last Byte is received, disable Interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_BUF); + + /* Set state at HAL_SMBUS_STATE_LISTEN */ + hsmbus->PreviousState = SMBUS_STATE_SLAVE_BUSY_RX; + hsmbus->State = HAL_SMBUS_STATE_LISTEN; + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->SlaveRxCpltCallback(hsmbus); +#else + HAL_SMBUS_SlaveRxCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + return HAL_OK; +} + +/** + * @brief Handle BTF flag for Slave receiver + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_SlaveReceive_BTF(SMBUS_HandleTypeDef *hsmbus) +{ + if (hsmbus->XferCount != 0U) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + hsmbus->XferCount--; + } + + return HAL_OK; +} + +/** + * @brief Handle ADD flag for Slave + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Slave_ADDR(SMBUS_HandleTypeDef *hsmbus) +{ + uint8_t TransferDirection = SMBUS_DIRECTION_RECEIVE ; + uint16_t SlaveAddrCode = 0U; + + /* Transfer Direction requested by Master */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_TRA) == RESET) + { + TransferDirection = SMBUS_DIRECTION_TRANSMIT; + } + + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_DUALF) == RESET) + { + SlaveAddrCode = hsmbus->Init.OwnAddress1; + } + else + { + SlaveAddrCode = hsmbus->Init.OwnAddress2; + } + + /* Call Slave Addr callback */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->AddrCallback(hsmbus, TransferDirection, SlaveAddrCode); +#else + HAL_SMBUS_AddrCallback(hsmbus, TransferDirection, SlaveAddrCode); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + + return HAL_OK; +} + +/** + * @brief Handle STOPF flag for Slave + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Slave_STOPF(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Clear STOPF flag */ + __HAL_SMBUS_CLEAR_STOPFLAG(hsmbus); + + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + /* All data are not transferred, so set error code accordingly */ + if (hsmbus->XferCount != 0U) + { + /* Store Last receive data if any */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_BTF) == SET) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + + if (hsmbus->XferCount > 0) + { + hsmbus->XferSize--; + hsmbus->XferCount--; + } + } + + /* Store Last receive data if any */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + + if (hsmbus->XferCount > 0) + { + hsmbus->XferSize--; + hsmbus->XferCount--; + } + } + } + + if (hsmbus->ErrorCode != HAL_SMBUS_ERROR_NONE) + { + /* Call the corresponding callback to inform upper layer of End of Transfer */ + SMBUS_ITError(hsmbus); + } + else + { + if ((CurrentState == HAL_SMBUS_STATE_LISTEN) || (CurrentState == HAL_SMBUS_STATE_BUSY_RX_LISTEN) || \ + (CurrentState == HAL_SMBUS_STATE_BUSY_TX_LISTEN)) + { + hsmbus->XferOptions = SMBUS_NO_OPTION_FRAME; + hsmbus->PreviousState = HAL_SMBUS_STATE_READY; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->ListenCpltCallback(hsmbus); +#else + HAL_SMBUS_ListenCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + } + return HAL_OK; +} + +/** + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_Slave_AF(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variables to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + uint32_t CurrentXferOptions = hsmbus->XferOptions; + + if (((CurrentXferOptions == SMBUS_FIRST_AND_LAST_FRAME_NO_PEC) || (CurrentXferOptions == SMBUS_FIRST_AND_LAST_FRAME_WITH_PEC) || \ + (CurrentXferOptions == SMBUS_LAST_FRAME_NO_PEC) || (CurrentXferOptions == SMBUS_LAST_FRAME_WITH_PEC)) && \ + (CurrentState == HAL_SMBUS_STATE_LISTEN)) + { + hsmbus->XferOptions = SMBUS_NO_OPTION_FRAME; + + /* Disable EVT, BUF and ERR interrupt */ + __HAL_SMBUS_DISABLE_IT(hsmbus, SMBUS_IT_EVT | SMBUS_IT_BUF | SMBUS_IT_ERR); + + /* Clear AF flag */ + __HAL_SMBUS_CLEAR_FLAG(hsmbus, SMBUS_FLAG_AF); + + /* Disable Acknowledge */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_ACK); + + hsmbus->PreviousState = HAL_SMBUS_STATE_READY; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->ListenCpltCallback(hsmbus); +#else + HAL_SMBUS_ListenCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + return HAL_OK; +} + + + +/** + * @brief SMBUS interrupts error process + * @param hsmbus SMBUS handle. + * @retval None + */ +static void SMBUS_ITError(SMBUS_HandleTypeDef *hsmbus) +{ + /* Declaration of temporary variable to prevent undefined behavior of volatile usage */ + uint32_t CurrentState = hsmbus->State; + + if ((CurrentState == HAL_SMBUS_STATE_BUSY_TX_LISTEN) || (CurrentState == HAL_SMBUS_STATE_BUSY_RX_LISTEN)) + { + /* keep HAL_SMBUS_STATE_LISTEN */ + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_LISTEN; + } + else + { + /* If state is an abort treatment on going, don't change state */ + /* This change will be done later */ + if (hsmbus->State != HAL_SMBUS_STATE_ABORT) + { + hsmbus->State = HAL_SMBUS_STATE_READY; + } + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + } + + /* Disable Pos bit in SMBUS CR1 when error occurred in Master/Mem Receive IT Process */ + CLEAR_BIT(hsmbus->Instance->CR1, I2C_CR1_POS); + + if (hsmbus->State == HAL_SMBUS_STATE_ABORT) + { + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->ErrorCode = HAL_SMBUS_ERROR_NONE; + + /* Store Last receive data if any */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + } + + /* Disable SMBUS peripheral to prevent dummy data in buffer */ + __HAL_SMBUS_DISABLE(hsmbus); + + /* Call the corresponding callback to inform upper layer of End of Transfer */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->AbortCpltCallback(hsmbus); +#else + HAL_SMBUS_AbortCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + else + { + /* Store Last receive data if any */ + if (__HAL_SMBUS_GET_FLAG(hsmbus, SMBUS_FLAG_RXNE) == SET) + { + /* Read data from DR */ + (*hsmbus->pBuffPtr++) = hsmbus->Instance->DR; + } + + /* Call user error callback */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->ErrorCallback(hsmbus); +#else + HAL_SMBUS_ErrorCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } + /* STOP Flag is not set after a NACK reception */ + /* So may inform upper layer that listen phase is stopped */ + /* during NACK error treatment */ + if ((hsmbus->State == HAL_SMBUS_STATE_LISTEN) && ((hsmbus->ErrorCode & HAL_SMBUS_ERROR_AF) == HAL_SMBUS_ERROR_AF)) + { + hsmbus->XferOptions = SMBUS_NO_OPTION_FRAME; + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + + /* Call the Listen Complete callback, to inform upper layer of the end of Listen usecase */ +#if (USE_HAL_SMBUS_REGISTER_CALLBACKS == 1) + hsmbus->ListenCpltCallback(hsmbus); +#else + HAL_SMBUS_ListenCpltCallback(hsmbus); +#endif /* USE_HAL_SMBUS_REGISTER_CALLBACKS */ + } +} + +/** + * @brief This function handles SMBUS Communication Timeout. + * @param hsmbus Pointer to a SMBUS_HandleTypeDef structure that contains + * the configuration information for SMBUS module + * @param Flag specifies the SMBUS flag to check. + * @param Status The new Flag status (SET or RESET). + * @param Timeout Timeout duration + * @param Tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SMBUS_WaitOnFlagUntilTimeout(SMBUS_HandleTypeDef *hsmbus, uint32_t Flag, FlagStatus Status, uint32_t Timeout, uint32_t Tickstart) +{ + /* Wait until flag is set */ + if (Status == RESET) + { + while (__HAL_SMBUS_GET_FLAG(hsmbus, Flag) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + hsmbus->PreviousState = SMBUS_STATE_NONE; + hsmbus->State = HAL_SMBUS_STATE_READY; + hsmbus->Mode = HAL_SMBUS_MODE_NONE; + + /* Process Unlocked */ + __HAL_UNLOCK(hsmbus); + return HAL_TIMEOUT; + } + } + } + } + return HAL_OK; +} + +/** + * @} + */ + + +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c new file mode 100644 index 0000000..da7c302 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spdifrx.c @@ -0,0 +1,1627 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_spdifrx.c + * @author MCD Application Team + * @brief This file provides firmware functions to manage the following + * functionalities of the SPDIFRX audio interface: + * + Initialization and Configuration + * + Data transfers functions + * + DMA transfers management + * + Interrupts and flags management + * + ****************************************************************************** + * @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 SPDIFRX HAL driver can be used as follow: + + (#) Declare SPDIFRX_HandleTypeDef handle structure. + (#) Initialize the SPDIFRX low level resources by implement the HAL_SPDIFRX_MspInit() API: + (##) Enable the SPDIFRX interface clock. + (##) SPDIFRX pins configuration: + (+++) Enable the clock for the SPDIFRX GPIOs. + (+++) Configure these SPDIFRX pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_SPDIFRX_ReceiveControlFlow_IT() and HAL_SPDIFRX_ReceiveDataFlow_IT() API's). + (+++) Configure the SPDIFRX interrupt priority. + (+++) Enable the NVIC SPDIFRX IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_SPDIFRX_ReceiveDataFlow_DMA() and HAL_SPDIFRX_ReceiveControlFlow_DMA() API's). + (+++) Declare a DMA handle structure for the reception of the Data Flow channel. + (+++) Declare a DMA handle structure for the reception of the Control Flow channel. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure CtrlRx/DataRx with the required parameters. + (+++) Configure the DMA Channel. + (+++) Associate the initialized DMA handle to the SPDIFRX DMA CtrlRx/DataRx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the + DMA CtrlRx/DataRx channel. + + (#) Program the input selection, re-tries number, wait for activity, channel status selection, data format, stereo mode and masking of user bits + using HAL_SPDIFRX_Init() function. + + -@- The specific SPDIFRX interrupts (RXNE/CSRNE and Error Interrupts) will be managed using the macros + __SPDIFRX_ENABLE_IT() and __SPDIFRX_DISABLE_IT() inside the receive process. + -@- Make sure that ck_spdif clock is configured. + + (#) Three operation modes are available within this driver : + + *** Polling mode for reception operation (for debug purpose) *** + ================================================================ + [..] + (+) Receive data flow in blocking mode using HAL_SPDIFRX_ReceiveDataFlow() + (+) Receive control flow of data in blocking mode using HAL_SPDIFRX_ReceiveControlFlow() + + *** Interrupt mode for reception operation *** + ========================================= + [..] + (+) Receive an amount of data (Data Flow) in non blocking mode using HAL_SPDIFRX_ReceiveDataFlow_IT() + (+) Receive an amount of data (Control Flow) in non blocking mode using HAL_SPDIFRX_ReceiveControlFlow_IT() + (+) At reception end of half transfer HAL_SPDIFRX_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_RxHalfCpltCallback + (+) At reception end of transfer HAL_SPDIFRX_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_RxCpltCallback + (+) In case of transfer Error, HAL_SPDIFRX_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_ErrorCallback + + *** DMA mode for reception operation *** + ======================================== + [..] + (+) Receive an amount of data (Data Flow) in non blocking mode (DMA) using HAL_SPDIFRX_ReceiveDataFlow_DMA() + (+) Receive an amount of data (Control Flow) in non blocking mode (DMA) using HAL_SPDIFRX_ReceiveControlFlow_DMA() + (+) At reception end of half transfer HAL_SPDIFRX_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_RxHalfCpltCallback + (+) At reception end of transfer HAL_SPDIFRX_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_RxCpltCallback + (+) In case of transfer Error, HAL_SPDIFRX_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_SPDIFRX_ErrorCallback + (+) Stop the DMA Transfer using HAL_SPDIFRX_DMAStop() + + *** SPDIFRX HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in SPDIFRX HAL driver. + (+) __HAL_SPDIFRX_IDLE: Disable the specified SPDIFRX peripheral (IDEL State) + (+) __HAL_SPDIFRX_SYNC: Enable the synchronization state of the specified SPDIFRX peripheral (SYNC State) + (+) __HAL_SPDIFRX_RCV: Enable the receive state of the specified SPDIFRX peripheral (RCV State) + (+) __HAL_SPDIFRX_ENABLE_IT : Enable the specified SPDIFRX interrupts + (+) __HAL_SPDIFRX_DISABLE_IT : Disable the specified SPDIFRX interrupts + (+) __HAL_SPDIFRX_GET_FLAG: Check whether the specified SPDIFRX flag is set or not. + + [..] + (@) You can refer to the SPDIFRX HAL driver header file for more useful macros + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_SPDIFRX_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use HAL_SPDIFRX_RegisterCallback() function to register an interrupt callback. + + The HAL_SPDIFRX_RegisterCallback() function allows to register the following callbacks: + (+) RxHalfCpltCallback : SPDIFRX Data flow half completed callback. + (+) RxCpltCallback : SPDIFRX Data flow completed callback. + (+) CxHalfCpltCallback : SPDIFRX Control flow half completed callback. + (+) CxCpltCallback : SPDIFRX Control flow completed callback. + (+) ErrorCallback : SPDIFRX error callback. + (+) MspInitCallback : SPDIFRX MspInit. + (+) MspDeInitCallback : SPDIFRX MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use HAL_SPDIFRX_UnRegisterCallback() function to reset a callback to the default + weak function. + The HAL_SPDIFRX_UnRegisterCallback() function takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset the following callbacks: + (+) RxHalfCpltCallback : SPDIFRX Data flow half completed callback. + (+) RxCpltCallback : SPDIFRX Data flow completed callback. + (+) CxHalfCpltCallback : SPDIFRX Control flow half completed callback. + (+) CxCpltCallback : SPDIFRX Control flow completed callback. + (+) ErrorCallback : SPDIFRX error callback. + (+) MspInitCallback : SPDIFRX MspInit. + (+) MspDeInitCallback : SPDIFRX MspDeInit. + + By default, after the HAL_SPDIFRX_Init() and when the state is HAL_SPDIFRX_STATE_RESET + all callbacks are set to the corresponding weak functions : + HAL_SPDIFRX_RxHalfCpltCallback() , HAL_SPDIFRX_RxCpltCallback(), HAL_SPDIFRX_CxHalfCpltCallback(), + HAL_SPDIFRX_CxCpltCallback() and HAL_SPDIFRX_ErrorCallback() + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_SPDIFRX_Init()/ HAL_SPDIFRX_DeInit() only when + these callbacks pointers are NULL (not registered beforehand). + If not, MspInit or MspDeInit callbacks pointers are not null, the HAL_SPDIFRX_Init() / HAL_SPDIFRX_DeInit() + keep and use the user MspInit/MspDeInit functions (registered beforehand) + + Callbacks can be registered/unregistered in HAL_SPDIFRX_STATE_READY state only. + Exception done MspInit/MspDeInit callbacks that can be registered/unregistered + in HAL_SPDIFRX_STATE_READY or HAL_SPDIFRX_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_SPDIFRX_RegisterCallback() before calling HAL_SPDIFRX_DeInit() + or HAL_SPDIFRX_Init() function. + + When The compilation define USE_HAL_SPDIFRX_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SPDIFRX SPDIFRX + * @brief SPDIFRX HAL module driver + * @{ + */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED +#if defined (SPDIFRX) +#if defined(STM32F446xx) +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define SPDIFRX_TIMEOUT_VALUE 0xFFFFU + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @addtogroup SPDIFRX_Private_Functions + * @{ + */ +static void SPDIFRX_DMARxCplt(DMA_HandleTypeDef *hdma); +static void SPDIFRX_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void SPDIFRX_DMACxCplt(DMA_HandleTypeDef *hdma); +static void SPDIFRX_DMACxHalfCplt(DMA_HandleTypeDef *hdma); +static void SPDIFRX_DMAError(DMA_HandleTypeDef *hdma); +static void SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif); +static void SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif); +static HAL_StatusTypeDef SPDIFRX_WaitOnFlagUntilTimeout(SPDIFRX_HandleTypeDef *hspdif, uint32_t Flag, + FlagStatus Status, uint32_t Timeout, uint32_t tickstart); +/** + * @} + */ +/* Exported functions ---------------------------------------------------------*/ + +/** @defgroup SPDIFRX_Exported_Functions SPDIFRX Exported Functions + * @{ + */ + +/** @defgroup SPDIFRX_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + de-initialize the SPDIFRX peripheral: + + (+) User must Implement HAL_SPDIFRX_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_SPDIFRX_Init() to configure the SPDIFRX peripheral with + the selected configuration: + (++) Input Selection (IN0, IN1,...) + (++) Maximum allowed re-tries during synchronization phase + (++) Wait for activity on SPDIF selected input + (++) Channel status selection (from channel A or B) + (++) Data format (LSB, MSB, ...) + (++) Stereo mode + (++) User bits masking (PT,C,U,V,...) + + (+) Call the function HAL_SPDIFRX_DeInit() to restore the default configuration + of the selected SPDIFRXx peripheral. + @endverbatim + * @{ + */ + +/** + * @brief Initializes the SPDIFRX according to the specified parameters + * in the SPDIFRX_InitTypeDef and create the associated handle. + * @param hspdif SPDIFRX handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_Init(SPDIFRX_HandleTypeDef *hspdif) +{ + uint32_t tmpreg; + + /* Check the SPDIFRX handle allocation */ + if (hspdif == NULL) + { + return HAL_ERROR; + } + + /* Check the SPDIFRX parameters */ + assert_param(IS_STEREO_MODE(hspdif->Init.StereoMode)); + assert_param(IS_SPDIFRX_INPUT_SELECT(hspdif->Init.InputSelection)); + assert_param(IS_SPDIFRX_MAX_RETRIES(hspdif->Init.Retries)); + assert_param(IS_SPDIFRX_WAIT_FOR_ACTIVITY(hspdif->Init.WaitForActivity)); + assert_param(IS_SPDIFRX_CHANNEL(hspdif->Init.ChannelSelection)); + assert_param(IS_SPDIFRX_DATA_FORMAT(hspdif->Init.DataFormat)); + assert_param(IS_PREAMBLE_TYPE_MASK(hspdif->Init.PreambleTypeMask)); + assert_param(IS_CHANNEL_STATUS_MASK(hspdif->Init.ChannelStatusMask)); + assert_param(IS_VALIDITY_MASK(hspdif->Init.ValidityBitMask)); + assert_param(IS_PARITY_ERROR_MASK(hspdif->Init.ParityErrorMask)); + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + if (hspdif->State == HAL_SPDIFRX_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hspdif->Lock = HAL_UNLOCKED; + + hspdif->RxHalfCpltCallback = HAL_SPDIFRX_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + hspdif->RxCpltCallback = HAL_SPDIFRX_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hspdif->CxHalfCpltCallback = HAL_SPDIFRX_CxHalfCpltCallback; /* Legacy weak CxHalfCpltCallback */ + hspdif->CxCpltCallback = HAL_SPDIFRX_CxCpltCallback; /* Legacy weak CxCpltCallback */ + hspdif->ErrorCallback = HAL_SPDIFRX_ErrorCallback; /* Legacy weak ErrorCallback */ + + if (hspdif->MspInitCallback == NULL) + { + hspdif->MspInitCallback = HAL_SPDIFRX_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware */ + hspdif->MspInitCallback(hspdif); + } +#else + if (hspdif->State == HAL_SPDIFRX_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hspdif->Lock = HAL_UNLOCKED; + /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ + HAL_SPDIFRX_MspInit(hspdif); + } +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + + /* SPDIFRX peripheral state is BUSY */ + hspdif->State = HAL_SPDIFRX_STATE_BUSY; + + /* Disable SPDIFRX interface (IDLE State) */ + __HAL_SPDIFRX_IDLE(hspdif); + + /* Reset the old SPDIFRX CR configuration */ + tmpreg = hspdif->Instance->CR; + + tmpreg &= ~(SPDIFRX_CR_RXSTEO | SPDIFRX_CR_DRFMT | SPDIFRX_CR_PMSK | + SPDIFRX_CR_VMSK | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK | + SPDIFRX_CR_CHSEL | SPDIFRX_CR_NBTR | SPDIFRX_CR_WFA | + SPDIFRX_CR_INSEL); + + /* Sets the new configuration of the SPDIFRX peripheral */ + tmpreg |= (hspdif->Init.StereoMode | + hspdif->Init.InputSelection | + hspdif->Init.Retries | + hspdif->Init.WaitForActivity | + hspdif->Init.ChannelSelection | + hspdif->Init.DataFormat | + hspdif->Init.PreambleTypeMask | + hspdif->Init.ChannelStatusMask | + hspdif->Init.ValidityBitMask | + hspdif->Init.ParityErrorMask + ); + + + hspdif->Instance->CR = tmpreg; + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + + /* SPDIFRX peripheral state is READY*/ + hspdif->State = HAL_SPDIFRX_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the SPDIFRX peripheral + * @param hspdif SPDIFRX handle + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_DeInit(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Check the SPDIFRX handle allocation */ + if (hspdif == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SPDIFRX_ALL_INSTANCE(hspdif->Instance)); + + hspdif->State = HAL_SPDIFRX_STATE_BUSY; + + /* Disable SPDIFRX interface (IDLE state) */ + __HAL_SPDIFRX_IDLE(hspdif); + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + if (hspdif->MspDeInitCallback == NULL) + { + hspdif->MspDeInitCallback = HAL_SPDIFRX_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware */ + hspdif->MspDeInitCallback(hspdif); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + HAL_SPDIFRX_MspDeInit(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + + /* SPDIFRX peripheral state is RESET*/ + hspdif->State = HAL_SPDIFRX_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; +} + +/** + * @brief SPDIFRX MSP Init + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_MspInit(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_MspInit could be implemented in the user file + */ +} + +/** + * @brief SPDIFRX MSP DeInit + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_MspDeInit(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User SPDIFRX Callback + * To be used instead of the weak predefined callback + * @param hspdif SPDIFRX handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SPDIFRX_RX_HALF_CB_ID SPDIFRX Data flow half completed callback ID + * @arg @ref HAL_SPDIFRX_RX_CPLT_CB_ID SPDIFRX Data flow completed callback ID + * @arg @ref HAL_SPDIFRX_CX_HALF_CB_ID SPDIFRX Control flow half completed callback ID + * @arg @ref HAL_SPDIFRX_CX_CPLT_CB_ID SPDIFRX Control flow completed callback ID + * @arg @ref HAL_SPDIFRX_ERROR_CB_ID SPDIFRX error callback ID + * @arg @ref HAL_SPDIFRX_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_SPDIFRX_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_RegisterCallback(SPDIFRX_HandleTypeDef *hspdif, HAL_SPDIFRX_CallbackIDTypeDef CallbackID, + pSPDIFRX_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hspdif); + + if (HAL_SPDIFRX_STATE_READY == hspdif->State) + { + switch (CallbackID) + { + case HAL_SPDIFRX_RX_HALF_CB_ID : + hspdif->RxHalfCpltCallback = pCallback; + break; + + case HAL_SPDIFRX_RX_CPLT_CB_ID : + hspdif->RxCpltCallback = pCallback; + break; + + case HAL_SPDIFRX_CX_HALF_CB_ID : + hspdif->CxHalfCpltCallback = pCallback; + break; + + case HAL_SPDIFRX_CX_CPLT_CB_ID : + hspdif->CxCpltCallback = pCallback; + break; + + case HAL_SPDIFRX_ERROR_CB_ID : + hspdif->ErrorCallback = pCallback; + break; + + case HAL_SPDIFRX_MSPINIT_CB_ID : + hspdif->MspInitCallback = pCallback; + break; + + case HAL_SPDIFRX_MSPDEINIT_CB_ID : + hspdif->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPDIFRX_STATE_RESET == hspdif->State) + { + switch (CallbackID) + { + case HAL_SPDIFRX_MSPINIT_CB_ID : + hspdif->MspInitCallback = pCallback; + break; + + case HAL_SPDIFRX_MSPDEINIT_CB_ID : + hspdif->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspdif); + return status; +} + +/** + * @brief Unregister a SPDIFRX Callback + * SPDIFRX callback is redirected to the weak predefined callback + * @param hspdif SPDIFRX handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SPDIFRX_RX_HALF_CB_ID SPDIFRX Data flow half completed callback ID + * @arg @ref HAL_SPDIFRX_RX_CPLT_CB_ID SPDIFRX Data flow completed callback ID + * @arg @ref HAL_SPDIFRX_CX_HALF_CB_ID SPDIFRX Control flow half completed callback ID + * @arg @ref HAL_SPDIFRX_CX_CPLT_CB_ID SPDIFRX Control flow completed callback ID + * @arg @ref HAL_SPDIFRX_ERROR_CB_ID SPDIFRX error callback ID + * @arg @ref HAL_SPDIFRX_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_SPDIFRX_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_UnRegisterCallback(SPDIFRX_HandleTypeDef *hspdif, + HAL_SPDIFRX_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hspdif); + + if (HAL_SPDIFRX_STATE_READY == hspdif->State) + { + switch (CallbackID) + { + case HAL_SPDIFRX_RX_HALF_CB_ID : + hspdif->RxHalfCpltCallback = HAL_SPDIFRX_RxHalfCpltCallback; + break; + + case HAL_SPDIFRX_RX_CPLT_CB_ID : + hspdif->RxCpltCallback = HAL_SPDIFRX_RxCpltCallback; + break; + + case HAL_SPDIFRX_CX_HALF_CB_ID : + hspdif->CxHalfCpltCallback = HAL_SPDIFRX_CxHalfCpltCallback; + break; + + case HAL_SPDIFRX_CX_CPLT_CB_ID : + hspdif->CxCpltCallback = HAL_SPDIFRX_CxCpltCallback; + break; + + case HAL_SPDIFRX_ERROR_CB_ID : + hspdif->ErrorCallback = HAL_SPDIFRX_ErrorCallback; + break; + + default : + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPDIFRX_STATE_RESET == hspdif->State) + { + switch (CallbackID) + { + case HAL_SPDIFRX_MSPINIT_CB_ID : + hspdif->MspInitCallback = HAL_SPDIFRX_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SPDIFRX_MSPDEINIT_CB_ID : + hspdif->MspDeInitCallback = HAL_SPDIFRX_MspDeInit; /* Legacy weak MspInit */ + break; + + default : + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspdif); + return status; +} + +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + +/** + * @brief Set the SPDIFRX data format according to the specified parameters in the SPDIFRX_InitTypeDef. + * @param hspdif SPDIFRX handle + * @param sDataFormat SPDIFRX data format + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_SetDataFormat(SPDIFRX_HandleTypeDef *hspdif, SPDIFRX_SetDataFormatTypeDef sDataFormat) +{ + uint32_t tmpreg; + + /* Check the SPDIFRX handle allocation */ + if (hspdif == NULL) + { + return HAL_ERROR; + } + + /* Check the SPDIFRX parameters */ + assert_param(IS_STEREO_MODE(sDataFormat.StereoMode)); + assert_param(IS_SPDIFRX_DATA_FORMAT(sDataFormat.DataFormat)); + assert_param(IS_PREAMBLE_TYPE_MASK(sDataFormat.PreambleTypeMask)); + assert_param(IS_CHANNEL_STATUS_MASK(sDataFormat.ChannelStatusMask)); + assert_param(IS_VALIDITY_MASK(sDataFormat.ValidityBitMask)); + assert_param(IS_PARITY_ERROR_MASK(sDataFormat.ParityErrorMask)); + + /* Reset the old SPDIFRX CR configuration */ + tmpreg = hspdif->Instance->CR; + + if (((tmpreg & SPDIFRX_STATE_RCV) == SPDIFRX_STATE_RCV) && + (((tmpreg & SPDIFRX_CR_DRFMT) != sDataFormat.DataFormat) || + ((tmpreg & SPDIFRX_CR_RXSTEO) != sDataFormat.StereoMode))) + { + return HAL_ERROR; + } + + tmpreg &= ~(SPDIFRX_CR_RXSTEO | SPDIFRX_CR_DRFMT | SPDIFRX_CR_PMSK | + SPDIFRX_CR_VMSK | SPDIFRX_CR_CUMSK | SPDIFRX_CR_PTMSK); + + /* Configure the new data format */ + tmpreg |= (sDataFormat.StereoMode | + sDataFormat.DataFormat | + sDataFormat.PreambleTypeMask | + sDataFormat.ChannelStatusMask | + sDataFormat.ValidityBitMask | + sDataFormat.ParityErrorMask); + + hspdif->Instance->CR = tmpreg; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup SPDIFRX_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim +=============================================================================== + ##### IO operation functions ##### +=============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SPDIFRX data + transfers. + + (#) There is two mode of transfer: + (++) Blocking mode : The communication is performed in the polling mode. + The status of all data processing is returned by the same function + after finishing transfer. + (++) No-Blocking mode : The communication is performed using Interrupts + or DMA. These functions return the status of the transfer start-up. + The end of the data processing will be indicated through the + dedicated SPDIFRX IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + + (#) Blocking mode functions are : + (++) HAL_SPDIFRX_ReceiveDataFlow() + (++) HAL_SPDIFRX_ReceiveControlFlow() + (+@) Do not use blocking mode to receive both control and data flow at the same time. + + (#) No-Blocking mode functions with Interrupt are : + (++) HAL_SPDIFRX_ReceiveControlFlow_IT() + (++) HAL_SPDIFRX_ReceiveDataFlow_IT() + + (#) No-Blocking mode functions with DMA are : + (++) HAL_SPDIFRX_ReceiveControlFlow_DMA() + (++) HAL_SPDIFRX_ReceiveDataFlow_DMA() + + (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode: + (++) HAL_SPDIFRX_RxCpltCallback() + (++) HAL_SPDIFRX_CxCpltCallback() + +@endverbatim + * @{ + */ + +/** + * @brief Receives an amount of data (Data Flow) in blocking mode. + * @param hspdif pointer to SPDIFRX_HandleTypeDef structure that contains + * the configuration information for SPDIFRX module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, + uint32_t Timeout) +{ + uint32_t tickstart; + uint16_t sizeCounter = Size; + uint32_t *pTmpBuf = pData; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (hspdif->State == HAL_SPDIFRX_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->State = HAL_SPDIFRX_STATE_BUSY; + + /* Start synchronisation */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until SYNCD flag is set */ + if (SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_SYNCD, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + + /* Receive data flow */ + while (sizeCounter > 0U) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until RXNE flag is set */ + if (SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + (*pTmpBuf) = hspdif->Instance->DR; + pTmpBuf++; + sizeCounter--; + } + + /* SPDIFRX ready */ + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receives an amount of data (Control Flow) in blocking mode. + * @param hspdif pointer to a SPDIFRX_HandleTypeDef structure that contains + * the configuration information for SPDIFRX module. + * @param pData Pointer to data buffer + * @param Size Amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size, + uint32_t Timeout) +{ + uint32_t tickstart; + uint16_t sizeCounter = Size; + uint32_t *pTmpBuf = pData; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if (hspdif->State == HAL_SPDIFRX_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->State = HAL_SPDIFRX_STATE_BUSY; + + /* Start synchronization */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until SYNCD flag is set */ + if (SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_SYNCD, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + + /* Receive control flow */ + while (sizeCounter > 0U) + { + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until CSRNE flag is set */ + if (SPDIFRX_WaitOnFlagUntilTimeout(hspdif, SPDIFRX_FLAG_CSRNE, RESET, Timeout, tickstart) != HAL_OK) + { + return HAL_TIMEOUT; + } + + (*pTmpBuf) = hspdif->Instance->CSR; + pTmpBuf++; + sizeCounter--; + } + + /* SPDIFRX ready */ + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data (Data Flow) in non-blocking mode with Interrupt + * @param hspdif SPDIFRX handle + * @param pData a 32-bit pointer to the Receive data buffer. + * @param Size number of data sample to be received . + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size) +{ + uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U); + + const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State; + + if ((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_CX)) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->pRxBuffPtr = pData; + hspdif->RxXferSize = Size; + hspdif->RxXferCount = Size; + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + + /* Check if a receive process is ongoing or not */ + hspdif->State = HAL_SPDIFRX_STATE_BUSY_RX; + + /* Enable the SPDIFRX PE Error Interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + + /* Enable the SPDIFRX OVR Error Interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + + /* Enable the SPDIFRX RXNE interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_RXNE); + + if ((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV) + { + /* Start synchronization */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Wait until SYNCD flag is set */ + do + { + if (count == 0U) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_TIMEOUT; + } + count--; + } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET); + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data (Control Flow) with Interrupt + * @param hspdif SPDIFRX handle + * @param pData a 32-bit pointer to the Receive data buffer. + * @param Size number of data sample (Control Flow) to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size) +{ + uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U); + + const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State; + + if ((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_RX)) + { + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->pCsBuffPtr = pData; + hspdif->CsXferSize = Size; + hspdif->CsXferCount = Size; + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + + /* Check if a receive process is ongoing or not */ + hspdif->State = HAL_SPDIFRX_STATE_BUSY_CX; + + /* Enable the SPDIFRX PE Error Interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + + /* Enable the SPDIFRX OVR Error Interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + + /* Enable the SPDIFRX CSRNE interrupt */ + __HAL_SPDIFRX_ENABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + + if ((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV) + { + /* Start synchronization */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Wait until SYNCD flag is set */ + do + { + if (count == 0U) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_TIMEOUT; + } + count--; + } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET); + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data (Data Flow) mode with DMA + * @param hspdif SPDIFRX handle + * @param pData a 32-bit pointer to the Receive data buffer. + * @param Size number of data sample to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveDataFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size) +{ + uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U); + + const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if ((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_CX)) + { + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->pRxBuffPtr = pData; + hspdif->RxXferSize = Size; + hspdif->RxXferCount = Size; + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + hspdif->State = HAL_SPDIFRX_STATE_BUSY_RX; + + /* Set the SPDIFRX Rx DMA Half transfer complete callback */ + hspdif->hdmaDrRx->XferHalfCpltCallback = SPDIFRX_DMARxHalfCplt; + + /* Set the SPDIFRX Rx DMA transfer complete callback */ + hspdif->hdmaDrRx->XferCpltCallback = SPDIFRX_DMARxCplt; + + /* Set the DMA error callback */ + hspdif->hdmaDrRx->XferErrorCallback = SPDIFRX_DMAError; + + /* Enable the DMA request */ + if (HAL_DMA_Start_IT(hspdif->hdmaDrRx, (uint32_t)&hspdif->Instance->DR, (uint32_t)hspdif->pRxBuffPtr, Size) != HAL_OK) + { + /* Set SPDIFRX error */ + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_DMA; + + /* Set SPDIFRX state */ + hspdif->State = HAL_SPDIFRX_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_ERROR; + } + + /* Enable RXDMAEN bit in SPDIFRX CR register for data flow reception*/ + hspdif->Instance->CR |= SPDIFRX_CR_RXDMAEN; + + if ((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV) + { + /* Start synchronization */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Wait until SYNCD flag is set */ + do + { + if (count == 0U) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_TIMEOUT; + } + count--; + } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET); + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Receive an amount of data (Control Flow) with DMA + * @param hspdif SPDIFRX handle + * @param pData a 32-bit pointer to the Receive data buffer. + * @param Size number of data (Control Flow) sample to be received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPDIFRX_ReceiveControlFlow_DMA(SPDIFRX_HandleTypeDef *hspdif, uint32_t *pData, uint16_t Size) +{ + uint32_t count = SPDIFRX_TIMEOUT_VALUE * (SystemCoreClock / 24U / 1000U); + + const HAL_SPDIFRX_StateTypeDef tempState = hspdif->State; + + if ((pData == NULL) || (Size == 0U)) + { + return HAL_ERROR; + } + + if ((tempState == HAL_SPDIFRX_STATE_READY) || (tempState == HAL_SPDIFRX_STATE_BUSY_RX)) + { + hspdif->pCsBuffPtr = pData; + hspdif->CsXferSize = Size; + hspdif->CsXferCount = Size; + + /* Process Locked */ + __HAL_LOCK(hspdif); + + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_NONE; + hspdif->State = HAL_SPDIFRX_STATE_BUSY_CX; + + /* Set the SPDIFRX Rx DMA Half transfer complete callback */ + hspdif->hdmaCsRx->XferHalfCpltCallback = SPDIFRX_DMACxHalfCplt; + + /* Set the SPDIFRX Rx DMA transfer complete callback */ + hspdif->hdmaCsRx->XferCpltCallback = SPDIFRX_DMACxCplt; + + /* Set the DMA error callback */ + hspdif->hdmaCsRx->XferErrorCallback = SPDIFRX_DMAError; + + /* Enable the DMA request */ + if (HAL_DMA_Start_IT(hspdif->hdmaCsRx, (uint32_t)&hspdif->Instance->CSR, (uint32_t)hspdif->pCsBuffPtr, Size) != HAL_OK) + { + /* Set SPDIFRX error */ + hspdif->ErrorCode = HAL_SPDIFRX_ERROR_DMA; + + /* Set SPDIFRX state */ + hspdif->State = HAL_SPDIFRX_STATE_ERROR; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_ERROR; + } + + /* Enable CBDMAEN bit in SPDIFRX CR register for control flow reception*/ + hspdif->Instance->CR |= SPDIFRX_CR_CBDMAEN; + + if ((SPDIFRX->CR & SPDIFRX_CR_SPDIFEN) != SPDIFRX_STATE_RCV) + { + /* Start synchronization */ + __HAL_SPDIFRX_SYNC(hspdif); + + /* Wait until SYNCD flag is set */ + do + { + if (count == 0U) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_TIMEOUT; + } + count--; + } while (__HAL_SPDIFRX_GET_FLAG(hspdif, SPDIFRX_FLAG_SYNCD) == RESET); + + /* Start reception */ + __HAL_SPDIFRX_RCV(hspdif); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief stop the audio stream receive from the Media. + * @param hspdif SPDIFRX handle + * @retval None + */ +HAL_StatusTypeDef HAL_SPDIFRX_DMAStop(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Process Locked */ + __HAL_LOCK(hspdif); + + /* Disable the SPDIFRX DMA requests */ + hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_RXDMAEN); + hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_CBDMAEN); + + /* Disable the SPDIFRX DMA channel */ + __HAL_DMA_DISABLE(hspdif->hdmaDrRx); + __HAL_DMA_DISABLE(hspdif->hdmaCsRx); + + /* Disable SPDIFRX peripheral */ + __HAL_SPDIFRX_IDLE(hspdif); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_OK; +} + +/** + * @brief This function handles SPDIFRX interrupt request. + * @param hspdif SPDIFRX handle + * @retval HAL status + */ +void HAL_SPDIFRX_IRQHandler(SPDIFRX_HandleTypeDef *hspdif) +{ + uint32_t itFlag = hspdif->Instance->SR; + uint32_t itSource = hspdif->Instance->IMR; + + /* SPDIFRX in mode Data Flow Reception */ + if (((itFlag & SPDIFRX_FLAG_RXNE) == SPDIFRX_FLAG_RXNE) && ((itSource & SPDIFRX_IT_RXNE) == SPDIFRX_IT_RXNE)) + { + __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_RXNE); + SPDIFRX_ReceiveDataFlow_IT(hspdif); + } + + /* SPDIFRX in mode Control Flow Reception */ + if (((itFlag & SPDIFRX_FLAG_CSRNE) == SPDIFRX_FLAG_CSRNE) && ((itSource & SPDIFRX_IT_CSRNE) == SPDIFRX_IT_CSRNE)) + { + __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_CSRNE); + SPDIFRX_ReceiveControlFlow_IT(hspdif); + } + + /* SPDIFRX Overrun error interrupt occurred */ + if (((itFlag & SPDIFRX_FLAG_OVR) == SPDIFRX_FLAG_OVR) && ((itSource & SPDIFRX_IT_OVRIE) == SPDIFRX_IT_OVRIE)) + { + __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_OVRIE); + + /* Change the SPDIFRX error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_OVR; + + /* the transfer is not stopped */ + HAL_SPDIFRX_ErrorCallback(hspdif); + } + + /* SPDIFRX Parity error interrupt occurred */ + if (((itFlag & SPDIFRX_FLAG_PERR) == SPDIFRX_FLAG_PERR) && ((itSource & SPDIFRX_IT_PERRIE) == SPDIFRX_IT_PERRIE)) + { + __HAL_SPDIFRX_CLEAR_IT(hspdif, SPDIFRX_IT_PERRIE); + + /* Change the SPDIFRX error code */ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_PE; + + /* the transfer is not stopped */ + HAL_SPDIFRX_ErrorCallback(hspdif); + } +} + +/** + * @brief Rx Transfer (Data flow) half completed callbacks + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_RxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer (Data flow) completed callbacks + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_RxCpltCallback(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx (Control flow) Transfer half completed callbacks + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_CxHalfCpltCallback(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer (Control flow) completed callbacks + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_CxCpltCallback(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief SPDIFRX error callbacks + * @param hspdif SPDIFRX handle + * @retval None + */ +__weak void HAL_SPDIFRX_ErrorCallback(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspdif); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SPDIFRX_ErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup SPDIFRX_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief Peripheral State functions + * +@verbatim +=============================================================================== +##### Peripheral State and Errors functions ##### +=============================================================================== +[..] +This subsection permit to get in run-time the status of the peripheral +and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Return the SPDIFRX state + * @param hspdif SPDIFRX handle + * @retval HAL state + */ +HAL_SPDIFRX_StateTypeDef HAL_SPDIFRX_GetState(SPDIFRX_HandleTypeDef const *const hspdif) +{ + return hspdif->State; +} + +/** + * @brief Return the SPDIFRX error code + * @param hspdif SPDIFRX handle + * @retval SPDIFRX Error Code + */ +uint32_t HAL_SPDIFRX_GetError(SPDIFRX_HandleTypeDef const *const hspdif) +{ + return hspdif->ErrorCode; +} + +/** + * @} + */ + +/** + * @brief DMA SPDIFRX receive process (Data flow) complete callback + * @param hdma DMA handle + * @retval None + */ +static void SPDIFRX_DMARxCplt(DMA_HandleTypeDef *hdma) +{ + SPDIFRX_HandleTypeDef *hspdif = (SPDIFRX_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Rx DMA Request */ + if (hdma->Init.Mode != DMA_CIRCULAR) + { + hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_RXDMAEN); + hspdif->RxXferCount = 0; + hspdif->State = HAL_SPDIFRX_STATE_READY; + } +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->RxCpltCallback(hspdif); +#else + HAL_SPDIFRX_RxCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPDIFRX receive process (Data flow) half complete callback + * @param hdma DMA handle + * @retval None + */ +static void SPDIFRX_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + SPDIFRX_HandleTypeDef *hspdif = (SPDIFRX_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->RxHalfCpltCallback(hspdif); +#else + HAL_SPDIFRX_RxHalfCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +} + + +/** + * @brief DMA SPDIFRX receive process (Control flow) complete callback + * @param hdma DMA handle + * @retval None + */ +static void SPDIFRX_DMACxCplt(DMA_HandleTypeDef *hdma) +{ + SPDIFRX_HandleTypeDef *hspdif = (SPDIFRX_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Cb DMA Request */ + hspdif->Instance->CR &= (uint16_t)(~SPDIFRX_CR_CBDMAEN); + hspdif->CsXferCount = 0; + + hspdif->State = HAL_SPDIFRX_STATE_READY; +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->CxCpltCallback(hspdif); +#else + HAL_SPDIFRX_CxCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPDIFRX receive process (Control flow) half complete callback + * @param hdma DMA handle + * @retval None + */ +static void SPDIFRX_DMACxHalfCplt(DMA_HandleTypeDef *hdma) +{ + SPDIFRX_HandleTypeDef *hspdif = (SPDIFRX_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->CxHalfCpltCallback(hspdif); +#else + HAL_SPDIFRX_CxHalfCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPDIFRX communication error callback + * @param hdma DMA handle + * @retval None + */ +static void SPDIFRX_DMAError(DMA_HandleTypeDef *hdma) +{ + SPDIFRX_HandleTypeDef *hspdif = (SPDIFRX_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + /* Disable Rx and Cb DMA Request */ + hspdif->Instance->CR &= (uint16_t)(~(SPDIFRX_CR_RXDMAEN | SPDIFRX_CR_CBDMAEN)); + hspdif->RxXferCount = 0; + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Set the error code and execute error callback*/ + hspdif->ErrorCode |= HAL_SPDIFRX_ERROR_DMA; + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + /* The transfer is not stopped */ + hspdif->ErrorCallback(hspdif); +#else + /* The transfer is not stopped */ + HAL_SPDIFRX_ErrorCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ +} + +/** + * @brief Receive an amount of data (Data Flow) with Interrupt + * @param hspdif SPDIFRX handle + * @retval None + */ +static void SPDIFRX_ReceiveDataFlow_IT(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Receive data */ + (*hspdif->pRxBuffPtr) = hspdif->Instance->DR; + hspdif->pRxBuffPtr++; + hspdif->RxXferCount--; + + if (hspdif->RxXferCount == 0U) + { + /* Disable RXNE/PE and OVR interrupts */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE | SPDIFRX_IT_PERRIE | SPDIFRX_IT_RXNE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->RxCpltCallback(hspdif); +#else + HAL_SPDIFRX_RxCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Receive an amount of data (Control Flow) with Interrupt + * @param hspdif SPDIFRX handle + * @retval None + */ +static void SPDIFRX_ReceiveControlFlow_IT(SPDIFRX_HandleTypeDef *hspdif) +{ + /* Receive data */ + (*hspdif->pCsBuffPtr) = hspdif->Instance->CSR; + hspdif->pCsBuffPtr++; + hspdif->CsXferCount--; + + if (hspdif->CsXferCount == 0U) + { + /* Disable CSRNE interrupt */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + +#if (USE_HAL_SPDIFRX_REGISTER_CALLBACKS == 1) + hspdif->CxCpltCallback(hspdif); +#else + HAL_SPDIFRX_CxCpltCallback(hspdif); +#endif /* USE_HAL_SPDIFRX_REGISTER_CALLBACKS */ + } +} + +/** + * @brief This function handles SPDIFRX Communication Timeout. + * @param hspdif SPDIFRX handle + * @param Flag Flag checked + * @param Status Value of the flag expected + * @param Timeout Duration of the timeout + * @param tickstart Tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPDIFRX_WaitOnFlagUntilTimeout(SPDIFRX_HandleTypeDef *hspdif, uint32_t Flag, FlagStatus Status, + uint32_t Timeout, uint32_t tickstart) +{ + /* Wait until flag is set */ + while (__HAL_SPDIFRX_GET_FLAG(hspdif, Flag) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_RXNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_CSRNE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_PERRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_OVRIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SBLKIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_SYNCDIE); + __HAL_SPDIFRX_DISABLE_IT(hspdif, SPDIFRX_IT_IFEIE); + + hspdif->State = HAL_SPDIFRX_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspdif); + + return HAL_TIMEOUT; + } + } + } + + return HAL_OK; +} + +/** + * @} + */ +#endif /* STM32F446xx */ + +#endif /* SPDIFRX */ +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c new file mode 100644 index 0000000..416b1ec --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_spi.c @@ -0,0 +1,3935 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_spi.c + * @author MCD Application Team + * @brief SPI HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Serial Peripheral Interface (SPI) peripheral: + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State 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 SPI HAL driver can be used as follows: + + (#) Declare a SPI_HandleTypeDef handle structure, for example: + SPI_HandleTypeDef hspi; + + (#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API: + (##) Enable the SPIx interface clock + (##) SPI pins configuration + (+++) Enable the clock for the SPI GPIOs + (+++) Configure these SPI pins as alternate function push-pull + (##) NVIC configuration if you need to use interrupt process + (+++) Configure the SPIx interrupt priority + (+++) Enable the NVIC SPI IRQ handle + (##) DMA Configuration if you need to use DMA process + (+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel + (+++) Enable the DMAx clock + (+++) Configure the DMA handle parameters + (+++) Configure the DMA Tx or Rx Stream/Channel + (+++) Associate the initialized hdma_tx(or _rx) handle to the hspi DMA Tx or Rx handle + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx or Rx Stream/Channel + + (#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS + management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure. + + (#) Initialize the SPI registers by calling the HAL_SPI_Init() API: + (++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_SPI_MspInit() API. + [..] + Circular mode restriction: + (#) The DMA circular mode cannot be used when the SPI is configured in these modes: + (##) Master 2Lines RxOnly + (##) Master 1Line Rx + (#) The CRC feature is not managed when the DMA circular mode is enabled + (#) When the SPI DMA Pause/Stop features are used, we must use the following APIs + the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks + [..] + Master Receive mode restriction: + (#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or + bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI + does not initiate a new transfer the following procedure has to be respected: + (##) HAL_SPI_DeInit() + (##) HAL_SPI_Init() + [..] + Callback registration: + + (#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U + allows the user to configure dynamically the driver callbacks. + Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback. + + Function HAL_SPI_RegisterCallback() allows to register following callbacks: + (++) TxCpltCallback : SPI Tx Completed callback + (++) RxCpltCallback : SPI Rx Completed callback + (++) TxRxCpltCallback : SPI TxRx Completed callback + (++) TxHalfCpltCallback : SPI Tx Half Completed callback + (++) RxHalfCpltCallback : SPI Rx Half Completed callback + (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback + (++) ErrorCallback : SPI Error callback + (++) AbortCpltCallback : SPI Abort callback + (++) MspInitCallback : SPI Msp Init callback + (++) MspDeInitCallback : SPI Msp DeInit callback + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + + (#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default + weak function. + HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (++) TxCpltCallback : SPI Tx Completed callback + (++) RxCpltCallback : SPI Rx Completed callback + (++) TxRxCpltCallback : SPI TxRx Completed callback + (++) TxHalfCpltCallback : SPI Tx Half Completed callback + (++) RxHalfCpltCallback : SPI Rx Half Completed callback + (++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback + (++) ErrorCallback : SPI Error callback + (++) AbortCpltCallback : SPI Abort callback + (++) MspInitCallback : SPI Msp Init callback + (++) MspDeInitCallback : SPI Msp DeInit callback + + [..] + By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when + these callbacks are null (not registered beforehand). + If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state. + + [..] + Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only. + Exception done MspInit/MspDeInit functions that can be registered/unregistered + in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + Then, the user first registers the MspInit/MspDeInit user callbacks + using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit() + or HAL_SPI_Init() function. + + [..] + When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + [..] + Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes, + the following table resume the max SPI frequency reached with data size 8bits/16bits, + according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance. + + @endverbatim + + Additional table : + + DataSize = SPI_DATASIZE_8BIT: + +----------------------------------------------------------------------------------------------+ + | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line | + | Process | Transfer mode |---------------------|----------------------|----------------------| + | | | Master | Slave | Master | Slave | Master | Slave | + |==============================================================================================| + | T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | / | Interrupt | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA | + | R |----------------|----------|----------|-----------|----------|-----------|----------| + | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | R | Interrupt | Fpclk/8 | Fpclk/8 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128| + +----------------------------------------------------------------------------------------------+ + + DataSize = SPI_DATASIZE_16BIT: + +----------------------------------------------------------------------------------------------+ + | | | 2Lines Fullduplex | 2Lines RxOnly | 1Line | + | Process | Transfer mode |---------------------|----------------------|----------------------| + | | | Master | Slave | Master | Slave | Master | Slave | + |==============================================================================================| + | T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | / | Interrupt | Fpclk/4 | Fpclk/4 | NA | NA | NA | NA | + | R |----------------|----------|----------|-----------|----------|-----------|----------| + | X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/32 | Fpclk/2 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | R | Interrupt | Fpclk/4 | Fpclk/4 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 | + |=========|================|==========|==========|===========|==========|===========|==========| + | | Polling | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/32 | + | |----------------|----------|----------|-----------|----------|-----------|----------| + | T | Interrupt | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/64 | + | X |----------------|----------|----------|-----------|----------|-----------|----------| + | | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128| + +----------------------------------------------------------------------------------------------+ + @note The max SPI frequency depend on SPI data size (8bits, 16bits), + SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA). + @note + (#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and HAL_SPI_TransmitReceive_DMA() + (#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA() + (#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA() + + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SPI SPI + * @brief SPI HAL module driver + * @{ + */ +#ifdef HAL_SPI_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private defines -----------------------------------------------------------*/ +/** @defgroup SPI_Private_Constants SPI Private Constants + * @{ + */ +#define SPI_DEFAULT_TIMEOUT 100U +#define SPI_BSY_FLAG_WORKAROUND_TIMEOUT 1000U /*!< Timeout 1000 µs */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup SPI_Private_Functions SPI Private Functions + * @{ + */ +static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma); +static void SPI_DMAError(DMA_HandleTypeDef *hdma); +static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State, + uint32_t Timeout, uint32_t Tickstart); +static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi); +#if (USE_SPI_CRC != 0U) +static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi); +static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi); +#endif /* USE_SPI_CRC */ +static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi); +static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi); +static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart); +static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup SPI_Exported_Functions SPI Exported Functions + * @{ + */ + +/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization and de-initialization functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + de-initialize the SPIx peripheral: + + (+) User must implement HAL_SPI_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ). + + (+) Call the function HAL_SPI_Init() to configure the selected device with + the selected configuration: + (++) Mode + (++) Direction + (++) Data Size + (++) Clock Polarity and Phase + (++) NSS Management + (++) BaudRate Prescaler + (++) FirstBit + (++) TIMode + (++) CRC Calculation + (++) CRC Polynomial if CRC enabled + + (+) Call the function HAL_SPI_DeInit() to restore the default configuration + of the selected SPIx peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the SPI according to the specified parameters + * in the SPI_InitTypeDef and initialize the associated handle. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi) +{ + /* Check the SPI handle allocation */ + if (hspi == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance)); + assert_param(IS_SPI_MODE(hspi->Init.Mode)); + assert_param(IS_SPI_DIRECTION(hspi->Init.Direction)); + assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize)); + assert_param(IS_SPI_NSS(hspi->Init.NSS)); + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit)); + assert_param(IS_SPI_TIMODE(hspi->Init.TIMode)); + if (hspi->Init.TIMode == SPI_TIMODE_DISABLE) + { + assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity)); + assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase)); + + if (hspi->Init.Mode == SPI_MODE_MASTER) + { + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + } + else + { + /* Baudrate prescaler not use in Motoraola Slave mode. force to default value */ + hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + } + } + else + { + assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler)); + + /* Force polarity and phase to TI protocaol requirements */ + hspi->Init.CLKPolarity = SPI_POLARITY_LOW; + hspi->Init.CLKPhase = SPI_PHASE_1EDGE; + } +#if (USE_SPI_CRC != 0U) + assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation)); + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial)); + } +#else + hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; +#endif /* USE_SPI_CRC */ + + if (hspi->State == HAL_SPI_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hspi->Lock = HAL_UNLOCKED; + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + /* Init the SPI Callback settings */ + hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */ + hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */ + hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ + hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */ + hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + + if (hspi->MspInitCallback == NULL) + { + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + } + + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + hspi->MspInitCallback(hspi); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC... */ + HAL_SPI_MspInit(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + + hspi->State = HAL_SPI_STATE_BUSY; + + /* Disable the selected SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + + /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/ + /* Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management, + Communication speed, First bit and CRC calculation state */ + WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) | + (hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) | + (hspi->Init.DataSize & SPI_CR1_DFF) | + (hspi->Init.CLKPolarity & SPI_CR1_CPOL) | + (hspi->Init.CLKPhase & SPI_CR1_CPHA) | + (hspi->Init.NSS & SPI_CR1_SSM) | + (hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) | + (hspi->Init.FirstBit & SPI_CR1_LSBFIRST) | + (hspi->Init.CRCCalculation & SPI_CR1_CRCEN))); + + /* Configure : NSS management, TI Mode */ + WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) | (hspi->Init.TIMode & SPI_CR2_FRF))); + +#if (USE_SPI_CRC != 0U) + /*---------------------------- SPIx CRCPOLY Configuration ------------------*/ + /* Configure : CRC Polynomial */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk)); + } +#endif /* USE_SPI_CRC */ + +#if defined(SPI_I2SCFGR_I2SMOD) + /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */ + CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD); +#endif /* SPI_I2SCFGR_I2SMOD */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_READY; + + return HAL_OK; +} + +/** + * @brief De-Initialize the SPI peripheral. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi) +{ + /* Check the SPI handle allocation */ + if (hspi == NULL) + { + return HAL_ERROR; + } + + /* Check SPI Instance parameter */ + assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance)); + + hspi->State = HAL_SPI_STATE_BUSY; + + /* Disable the SPI Peripheral Clock */ + __HAL_SPI_DISABLE(hspi); + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + if (hspi->MspDeInitCallback == NULL) + { + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + } + + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + hspi->MspDeInitCallback(hspi); +#else + /* DeInit the low level hardware: GPIO, CLOCK, NVIC... */ + HAL_SPI_MspDeInit(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->State = HAL_SPI_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Initialize the SPI MSP. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_MspInit should be implemented in the user file + */ +} + +/** + * @brief De-Initialize the SPI MSP. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_MspDeInit should be implemented in the user file + */ +} + +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) +/** + * @brief Register a User SPI Callback + * To be used instead of the weak predefined callback + * @param hspi Pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI. + * @param CallbackID ID of the callback to be registered + * @param pCallback pointer to the Callback function + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, + pSPI_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(hspi); + + if (HAL_SPI_STATE_READY == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_TX_COMPLETE_CB_ID : + hspi->TxCpltCallback = pCallback; + break; + + case HAL_SPI_RX_COMPLETE_CB_ID : + hspi->RxCpltCallback = pCallback; + break; + + case HAL_SPI_TX_RX_COMPLETE_CB_ID : + hspi->TxRxCpltCallback = pCallback; + break; + + case HAL_SPI_TX_HALF_COMPLETE_CB_ID : + hspi->TxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_RX_HALF_COMPLETE_CB_ID : + hspi->RxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID : + hspi->TxRxHalfCpltCallback = pCallback; + break; + + case HAL_SPI_ERROR_CB_ID : + hspi->ErrorCallback = pCallback; + break; + + case HAL_SPI_ABORT_CB_ID : + hspi->AbortCpltCallback = pCallback; + break; + + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = pCallback; + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPI_STATE_RESET == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = pCallback; + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspi); + return status; +} + +/** + * @brief Unregister an SPI Callback + * SPI callback is redirected to the weak predefined callback + * @param hspi Pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI. + * @param CallbackID ID of the callback to be unregistered + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(hspi); + + if (HAL_SPI_STATE_READY == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_TX_COMPLETE_CB_ID : + hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_SPI_RX_COMPLETE_CB_ID : + hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_SPI_TX_RX_COMPLETE_CB_ID : + hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + break; + + case HAL_SPI_TX_HALF_COMPLETE_CB_ID : + hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_SPI_RX_HALF_COMPLETE_CB_ID : + hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID : + hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */ + break; + + case HAL_SPI_ERROR_CB_ID : + hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_SPI_ABORT_CB_ID : + hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (HAL_SPI_STATE_RESET == hspi->State) + { + switch (CallbackID) + { + case HAL_SPI_MSPINIT_CB_ID : + hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */ + break; + + case HAL_SPI_MSPDEINIT_CB_ID : + hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */ + break; + + default : + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK); + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hspi); + return status; +} +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +/** + * @} + */ + +/** @defgroup SPI_Exported_Functions_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SPI + data transfers. + + [..] The SPI supports master and slave mode : + + (#) 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. + (++) No-Blocking mode: The communication is performed using Interrupts + or DMA, These APIs return the HAL status. + The end of the data processing will be indicated through the + dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected + + (#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA) + exist for 1Line (simplex) and 2Lines (full duplex) modes. + +@endverbatim + * @{ + */ + +/** + * @brief Transmit an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ + uint32_t tickstart; + HAL_StatusTypeDef errorcode = HAL_OK; + uint16_t initial_TxXferCount; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + initial_TxXferCount = Size; + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Transmit data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + } + /* Transmit data in 16 Bit mode */ + while (hspi->TxXferCount > 0U) + { + /* Wait until TXE flag is set to send data */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) + { + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + } + /* Transmit data in 8 Bit mode */ + else + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + } + while (hspi->TxXferCount > 0U) + { + /* Wait until TXE flag is set to send data */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + } +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + errorcode = HAL_ERROR; + } + else + { + hspi->State = HAL_SPI_STATE_READY; + } + +error: + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Receive an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) +{ +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + uint32_t tickstart; + HAL_StatusTypeDef errorcode = HAL_OK; + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout); + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + /* this is done to handle the CRCNEXT before the latest data */ + hspi->RxXferCount--; + } +#endif /* USE_SPI_CRC */ + + /* Configure communication direction: 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Receive data in 8 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_8BIT) + { + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + { + /* Check the RXNE flag */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) + { + /* read the received data */ + (* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint8_t); + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + } + else + { + /* Transfer loop */ + while (hspi->RxXferCount > 0U) + { + /* Check the RXNE flag */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + } + else + { + /* Timeout management */ + if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + } + +#if (USE_SPI_CRC != 0U) + /* Handle the CRC Transmission */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* freeze the CRC before the latest data */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + + /* Read the latest data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + /* the latest data has not been received */ + errorcode = HAL_TIMEOUT; + goto error; + } + + /* Receive last data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + } + /* Receive last data in 8 Bit mode */ + else + { + (*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR; + } + + /* Wait the CRC data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + errorcode = HAL_TIMEOUT; + goto error; + } + + /* Read CRC to Flush DR and RXNE flag */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + errorcode = HAL_ERROR; + } + else + { + hspi->State = HAL_SPI_STATE_READY; + } + +error : + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Transmit and Receive an amount of data in blocking mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @param Size amount of data to be sent and received + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, + uint32_t Timeout) +{ + uint16_t initial_TxXferCount; + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Variable used to alternate Rx and Tx during transfer */ + uint32_t txallowed = 1U; + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + initial_TxXferCount = Size; + + if (!((tmp_state == HAL_SPI_STATE_READY) || \ + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferCount = Size; + hspi->RxXferSize = Size; + hspi->pTxBuffPtr = (uint8_t *)pTxData; + hspi->TxXferCount = Size; + hspi->TxXferSize = Size; + + /*Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Transmit and Receive data in 16 Bit mode */ + if (hspi->Init.DataSize == SPI_DATASIZE_16BIT) + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + { + /* Check TXE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U)) + { + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + } + + /* Check RXNE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U)) + { + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR; + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + } + if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + /* Transmit and Receive data in 8 Bit mode */ + else + { + if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U)) + { + *((__IO uint8_t *)&hspi->Instance->DR) = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint8_t); + hspi->TxXferCount--; + } + while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U)) + { + /* Check TXE flag */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U)) + { + *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + /* Next Data is a reception (Rx). Tx not allowed */ + txallowed = 0U; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + } + + /* Wait until RXNE flag is reset */ + if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U)) + { + (*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR; + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + /* Next Data is a Transmission (Tx). Tx is allowed */ + txallowed = 1U; + } + if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U)) + { + errorcode = HAL_TIMEOUT; + hspi->State = HAL_SPI_STATE_READY; + goto error; + } + } + } + +#if (USE_SPI_CRC != 0U) + /* Read CRC from DR to close CRC calculation process */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait until TXE flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK) + { + /* Error on the CRC reception */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + errorcode = HAL_TIMEOUT; + goto error; + } + /* Read CRC */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } + + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + /* Clear CRC Flag */ + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + + errorcode = HAL_ERROR; + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK) + { + errorcode = HAL_ERROR; + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + goto error; + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + errorcode = HAL_ERROR; + } + else + { + hspi->State = HAL_SPI_STATE_READY; + } + +error : + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + hspi->RxISR = NULL; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->TxISR = SPI_TxISR_16BIT; + } + else + { + hspi->TxISR = SPI_TxISR_8BIT; + } + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable TXE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR)); + +error : + return errorcode; +} + +/** + * @brief Receive an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size); + } + + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pTxBuffPtr = (uint8_t *)NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + hspi->TxISR = NULL; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->RxISR = SPI_RxISR_16BIT; + } + else + { + hspi->RxISR = SPI_RxISR_8BIT; + } + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Note : The SPI must be enabled after unlocking current process + to avoid the risk of SPI interrupt handle execution before current + process unlock */ + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable RXNE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + +error : + return errorcode; +} + +/** + * @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @param Size amount of data to be sent and received + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size) +{ + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + + if (!((tmp_state == HAL_SPI_STATE_READY) || \ + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Process locked */ + __HAL_LOCK(hspi); + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pTxData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Set the function for IT treatment */ + if (hspi->Init.DataSize > SPI_DATASIZE_8BIT) + { + hspi->RxISR = SPI_2linesRxISR_16BIT; + hspi->TxISR = SPI_2linesTxISR_16BIT; + } + else + { + hspi->RxISR = SPI_2linesRxISR_8BIT; + hspi->TxISR = SPI_2linesTxISR_8BIT; + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + /* Enable TXE, RXNE and ERR interrupt */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR)); + +error : + return errorcode; +} + +/** + * @brief Transmit an amount of data in non-blocking mode with DMA. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check tx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction)); + + /* Process Locked */ + __HAL_LOCK(hspi); + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_TX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->pRxBuffPtr = (uint8_t *)NULL; + hspi->TxISR = NULL; + hspi->RxISR = NULL; + hspi->RxXferSize = 0U; + hspi->RxXferCount = 0U; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_TX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the SPI TxDMA Half transfer complete callback */ + hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt; + + /* Set the SPI TxDMA transfer complete callback */ + hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt; + + /* Set the DMA error callback */ + hspi->hdmatx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmatx->XferAbortCallback = NULL; + + /* Enable the Tx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, + hspi->TxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + + goto error; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Tx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + +error : + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Receive an amount of data in non-blocking mode with DMA. + * @note In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pData pointer to data buffer + * @note When the CRC feature is enabled the pData Length must be Size + 1. + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check rx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx)); + + if (hspi->State != HAL_SPI_STATE_READY) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + hspi->State = HAL_SPI_STATE_BUSY_RX; + + /* Check tx dma handle */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */ + return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size); + } + + /* Process Locked */ + __HAL_LOCK(hspi); + + if ((pData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Set the transaction information */ + hspi->State = HAL_SPI_STATE_BUSY_RX; + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pRxBuffPtr = (uint8_t *)pData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /*Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + hspi->TxXferSize = 0U; + hspi->TxXferCount = 0U; + + /* Configure communication direction : 1Line */ + if (hspi->Init.Direction == SPI_DIRECTION_1LINE) + { + /* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */ + __HAL_SPI_DISABLE(hspi); + SPI_1LINE_RX(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Set the SPI RxDMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt; + + /* Set the SPI Rx DMA transfer complete callback */ + hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt; + + /* Set the DMA error callback */ + hspi->hdmarx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Enable the Rx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, + hspi->RxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + + goto error; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Rx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + +error: + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Transmit and Receive an amount of data in non-blocking mode with DMA. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param pTxData pointer to transmission data buffer + * @param pRxData pointer to reception data buffer + * @note When the CRC feature is enabled the pRxData Length must be Size + 1 + * @param Size amount of data to be sent + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) +{ + uint32_t tmp_mode; + HAL_SPI_StateTypeDef tmp_state; + HAL_StatusTypeDef errorcode = HAL_OK; + + /* Check rx & tx dma handles */ + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx)); + assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx)); + + /* Check Direction parameter */ + assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction)); + + /* Process locked */ + __HAL_LOCK(hspi); + + /* Init temporary variables */ + tmp_state = hspi->State; + tmp_mode = hspi->Init.Mode; + + if (!((tmp_state == HAL_SPI_STATE_READY) || + ((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp_state == HAL_SPI_STATE_BUSY_RX)))) + { + errorcode = HAL_BUSY; + goto error; + } + + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U)) + { + errorcode = HAL_ERROR; + goto error; + } + + /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */ + if (hspi->State != HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_BUSY_TX_RX; + } + + /* Set the transaction information */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + hspi->pTxBuffPtr = (uint8_t *)pTxData; + hspi->TxXferSize = Size; + hspi->TxXferCount = Size; + hspi->pRxBuffPtr = (uint8_t *)pRxData; + hspi->RxXferSize = Size; + hspi->RxXferCount = Size; + + /* Init field not used in handle to zero */ + hspi->RxISR = NULL; + hspi->TxISR = NULL; + +#if (USE_SPI_CRC != 0U) + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } +#endif /* USE_SPI_CRC */ + + /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */ + if (hspi->State == HAL_SPI_STATE_BUSY_RX) + { + /* Set the SPI Rx DMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt; + hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt; + } + else + { + /* Set the SPI Tx/Rx DMA Half transfer complete callback */ + hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt; + hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt; + } + + /* Set the DMA error callback */ + hspi->hdmarx->XferErrorCallback = SPI_DMAError; + + /* Set the DMA AbortCpltCallback */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Enable the Rx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, + hspi->RxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + + goto error; + } + + /* Enable Rx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + + /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing + is performed in DMA reception complete callback */ + hspi->hdmatx->XferHalfCpltCallback = NULL; + hspi->hdmatx->XferCpltCallback = NULL; + hspi->hdmatx->XferErrorCallback = NULL; + hspi->hdmatx->XferAbortCallback = NULL; + + /* Enable the Tx DMA Stream/Channel */ + if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, + hspi->TxXferCount)) + { + /* Update SPI error code */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + + goto error; + } + + /* Check if the SPI is already enabled */ + if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) + { + /* Enable SPI peripheral */ + __HAL_SPI_ENABLE(hspi); + } + /* Enable the SPI Error Interrupt Bit */ + __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR)); + + /* Enable Tx DMA Request */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + +error : + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + return errorcode; +} + +/** + * @brief Abort ongoing transfer (blocking mode). + * @param hspi SPI handle. + * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx), + * started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SPI Interrupts (depending of transfer direction) + * - 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_SPI_Abort(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode; + __IO uint32_t count; + __IO uint32_t resetcount; + + /* Initialized local variable */ + errorcode = HAL_OK; + resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + count = resetcount; + + /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE); + + /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE)) + { + hspi->TxISR = SPI_AbortTx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE)) + { + hspi->RxISR = SPI_AbortRx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + /* Disable the SPI DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + /* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */ + if (hspi->hdmatx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */ + hspi->hdmatx->XferAbortCallback = NULL; + + /* Abort DMA Tx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN)); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + } + } + + /* Disable the SPI DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + /* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */ + if (hspi->hdmarx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */ + hspi->hdmarx->XferAbortCallback = NULL; + + /* Abort DMA Rx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + + /* Disable peripheral */ + __HAL_SPI_DISABLE(hspi); + + /* Disable Rx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN)); + } + } + /* Reset Tx and Rx transfer counters */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check error during Abort procedure */ + if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT) + { + /* return HAL_Error in case of error during Abort procedure */ + errorcode = HAL_ERROR; + } + else + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + __HAL_SPI_CLEAR_FREFLAG(hspi); + + /* Restore hspi->state to ready */ + hspi->State = HAL_SPI_STATE_READY; + + return errorcode; +} + +/** + * @brief Abort ongoing transfer (Interrupt mode). + * @param hspi SPI handle. + * @note This procedure could be used for aborting any ongoing transfer (Tx and Rx), + * started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable SPI Interrupts (depending of transfer direction) + * - 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_SPI_Abort_IT(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode; + uint32_t abortcplt ; + __IO uint32_t count; + __IO uint32_t resetcount; + + /* Initialized local variable */ + errorcode = HAL_OK; + abortcplt = 1U; + resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + count = resetcount; + + /* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE); + + /* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE)) + { + hspi->TxISR = SPI_AbortTx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE)) + { + hspi->RxISR = SPI_AbortRx_ISR; + /* Wait HAL_SPI_STATE_ABORT state */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while (hspi->State != HAL_SPI_STATE_ABORT); + /* Reset Timeout Counter */ + count = resetcount; + } + + /* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if (hspi->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback; + } + else + { + hspi->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if (hspi->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback; + } + else + { + hspi->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the SPI DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN)) + { + /* Abort the SPI DMA Tx Stream/Channel */ + if (hspi->hdmatx != NULL) + { + /* Abort DMA Tx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK) + { + hspi->hdmatx->XferAbortCallback = NULL; + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + else + { + abortcplt = 0U; + } + } + } + /* Disable the SPI DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN)) + { + /* Abort the SPI DMA Rx Stream/Channel */ + if (hspi->hdmarx != NULL) + { + /* Abort DMA Rx Handle linked to SPI Peripheral */ + if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK) + { + hspi->hdmarx->XferAbortCallback = NULL; + hspi->ErrorCode = HAL_SPI_ERROR_ABORT; + } + else + { + abortcplt = 0U; + } + } + } + + if (abortcplt == 1U) + { + /* Reset Tx and Rx transfer counters */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check error during Abort procedure */ + if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT) + { + /* return HAL_Error in case of error during Abort procedure */ + errorcode = HAL_ERROR; + } + else + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + __HAL_SPI_CLEAR_FREFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + + return errorcode; +} + +/** + * @brief Pause the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi) +{ + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Disable the SPI DMA Tx & Rx requests */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Resume the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi) +{ + /* Process Locked */ + __HAL_LOCK(hspi); + + /* Enable the SPI DMA Tx & Rx requests */ + SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_OK; +} + +/** + * @brief Stop the DMA Transfer. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi) +{ + HAL_StatusTypeDef errorcode = HAL_OK; + /* The Lock is not implemented on this API to allow the user application + to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or HAL_SPI_TxRxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or HAL_SPI_TxRxCpltCallback() + */ + + /* Abort the SPI DMA tx Stream/Channel */ + if (hspi->hdmatx != NULL) + { + if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + /* Abort the SPI DMA rx Stream/Channel */ + if (hspi->hdmarx != NULL) + { + if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + errorcode = HAL_ERROR; + } + } + + /* Disable the SPI DMA Tx & Rx requests */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + hspi->State = HAL_SPI_STATE_READY; + return errorcode; +} + +/** + * @brief Handle SPI interrupt request. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for the specified SPI module. + * @retval None + */ +void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi) +{ + uint32_t itsource = hspi->Instance->CR2; + uint32_t itflag = hspi->Instance->SR; + + /* SPI in mode Receiver ----------------------------------------------------*/ + if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) && + (SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET)) + { + hspi->RxISR(hspi); + return; + } + + /* SPI in mode Transmitter -------------------------------------------------*/ + if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET)) + { + hspi->TxISR(hspi); + return; + } + + /* SPI in Error Treatment --------------------------------------------------*/ + if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET) + || (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET)) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET)) + { + /* SPI Overrun error interrupt occurred ----------------------------------*/ + if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET) + { + if (hspi->State != HAL_SPI_STATE_BUSY_TX) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR); + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + else + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + return; + } + } + + /* SPI Mode Fault error interrupt occurred -------------------------------*/ + if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF); + __HAL_SPI_CLEAR_MODFFLAG(hspi); + } + + /* SPI Frame error interrupt occurred ------------------------------------*/ + if (SPI_CHECK_FLAG(itflag, SPI_FLAG_FRE) != RESET) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FRE); + __HAL_SPI_CLEAR_FREFLAG(hspi); + } + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Disable all interrupts */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR); + + hspi->State = HAL_SPI_STATE_READY; + /* Disable the SPI DMA requests if enabled */ + if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN))) + { + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN)); + + /* Abort the SPI DMA Rx channel */ + if (hspi->hdmarx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */ + hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError; + if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + } + /* Abort the SPI DMA Tx channel */ + if (hspi->hdmatx != NULL) + { + /* Set the SPI DMA Abort callback : + will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */ + hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError; + if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + } + return; + } +} + +/** + * @brief Tx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_RxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Tx and Rx Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxRxCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxHalfCpltCallback should be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file + */ +} + +/** + * @brief Tx and Rx Half Transfer callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file + */ +} + +/** + * @brief SPI error callback. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_ErrorCallback should be implemented in the user file + */ + /* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes + and user can use HAL_SPI_GetError() API to check the latest error occurred + */ +} + +/** + * @brief SPI Abort Complete callback. + * @param hspi SPI handle. + * @retval None + */ +__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hspi); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_SPI_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief SPI control functions + * +@verbatim + =============================================================================== + ##### Peripheral State and Errors functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the SPI. + (+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral + (+) HAL_SPI_GetError() check in run-time Errors occurring during communication +@endverbatim + * @{ + */ + +/** + * @brief Return the SPI handle state. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval SPI state + */ +HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *hspi) +{ + /* Return SPI handle state */ + return hspi->State; +} + +/** + * @brief Return the SPI error code. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval SPI error code in bitmap format + */ +uint32_t HAL_SPI_GetError(SPI_HandleTypeDef *hspi) +{ + /* Return SPI ErrorCode */ + return hspi->ErrorCode; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup SPI_Private_Functions + * @brief Private functions + * @{ + */ + +/** + * @brief DMA SPI 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 SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + uint32_t tickstart; + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) != DMA_SxCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received data is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + hspi->TxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user Tx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxCpltCallback(hspi); +#else + HAL_SPI_TxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI 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 SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) != DMA_SxCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + +#if (USE_SPI_CRC != 0U) + /* CRC handling */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait until RXNE flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + /* Error on the CRC reception */ + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + } + /* Read CRC */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check if we are in Master RX 2 line mode */ + if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER)) + { + /* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + } + else + { + /* Normal case */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + } + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + hspi->ErrorCode = HAL_SPI_ERROR_FLAG; + } + + hspi->RxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI transmit 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 SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + uint32_t tickstart; +#if (USE_SPI_CRC != 0U) + __IO uint32_t tmpreg = 0U; +#endif /* USE_SPI_CRC */ + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* DMA Normal Mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) != DMA_SxCR_CIRC) + { + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + +#if (USE_SPI_CRC != 0U) + /* CRC handling */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Wait the CRC data */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + } + /* Read CRC to Flush DR and RXNE flag */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + } +#endif /* USE_SPI_CRC */ + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Disable Rx/Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + hspi->TxXferCount = 0U; + hspi->RxXferCount = 0U; + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR)) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + } +#endif /* USE_SPI_CRC */ + + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + return; + } + } + /* Call user TxRx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxCpltCallback(hspi); +#else + HAL_SPI_TxRxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half 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 SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + + /* Call user Tx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxHalfCpltCallback(hspi); +#else + HAL_SPI_TxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half 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 SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + + /* Call user Rx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxHalfCpltCallback(hspi); +#else + HAL_SPI_RxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI half transmit 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 SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + + /* Call user TxRx half complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxHalfCpltCallback(hspi); +#else + HAL_SPI_TxRxHalfCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI 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 SPI_DMAError(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + + /* Stop the disable DMA transfer on SPI side */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN); + + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA); + hspi->State = HAL_SPI_STATE_READY; + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI 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 DMA handle. + * @retval None + */ +static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + __IO uint32_t count; + + hspi->hdmatx->XferAbortCallback = NULL; + count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Disable Tx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Check if an Abort process is still ongoing */ + if (hspi->hdmarx != NULL) + { + if (hspi->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check no error during Abort procedure */ + if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT) + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + __HAL_SPI_CLEAR_FREFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SPI 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 DMA handle. + * @retval None + */ +static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent); /* Derogation MISRAC2012-Rule-11.5 */ + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + hspi->hdmarx->XferAbortCallback = NULL; + + /* Disable Rx DMA Request */ + CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN); + + /* Check Busy flag */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + } + + /* Check if an Abort process is still ongoing */ + if (hspi->hdmatx != NULL) + { + if (hspi->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */ + hspi->RxXferCount = 0U; + hspi->TxXferCount = 0U; + + /* Check no error during Abort procedure */ + if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT) + { + /* Reset errorCode */ + hspi->ErrorCode = HAL_SPI_ERROR_NONE; + } + + /* Clear the Error flags in the SR register */ + __HAL_SPI_CLEAR_OVRFLAG(hspi); + __HAL_SPI_CLEAR_FREFLAG(hspi); + + /* Restore hspi->State to Ready */ + hspi->State = HAL_SPI_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->AbortCpltCallback(hspi); +#else + HAL_SPI_AbortCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ +} + +/** + * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Receive data in 8bit mode */ + *hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR); + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + + /* Check end of the reception */ + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_2linesRxISR_8BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint8_t *ptmpreg8; + __IO uint8_t tmpreg8 = 0; + + /* Initialize the 8bit temporary pointer */ + ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR; + /* Read 8bit CRC to flush Data Register */ + tmpreg8 = *ptmpreg8; + /* To avoid GCC warning */ + UNUSED(tmpreg8); + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + + /* Check the end of the transmission */ + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Set CRC Next Bit to send CRC */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + + if (hspi->RxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +/** + * @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Receive data in 16 Bit mode */ + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR); + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_2linesRxISR_16BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable RXNE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE); + + if (hspi->TxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + + /* Read 16bit CRC to flush Data Register */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + /* Disable RXNE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE); + + SPI_CloseRxTx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Transmit data in 16 Bit mode */ + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + + /* Enable CRC Transmission */ + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Set CRC Next Bit to send CRC */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + return; + } +#endif /* USE_SPI_CRC */ + + /* Disable TXE interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE); + + if (hspi->RxXferCount == 0U) + { + SPI_CloseRxTx_ISR(hspi); + } + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 8-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint8_t *ptmpreg8; + __IO uint8_t tmpreg8 = 0; + + /* Initialize the 8bit temporary pointer */ + ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR; + /* Read 8bit CRC to flush Data Register */ + tmpreg8 = *ptmpreg8; + /* To avoid GCC warning */ + UNUSED(tmpreg8); + + SPI_CloseRx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Manage the receive 8-bit in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR); + hspi->pRxBuffPtr++; + hspi->RxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_RxISR_8BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + SPI_CloseRx_ISR(hspi); + } +} + +#if (USE_SPI_CRC != 0U) +/** + * @brief Manage the CRC 16-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + + /* Read 16bit CRC to flush Data Register */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + SPI_CloseRx_ISR(hspi); +} +#endif /* USE_SPI_CRC */ + +/** + * @brief Manage the 16-bit receive in Interrupt context. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + *((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR); + hspi->pRxBuffPtr += sizeof(uint16_t); + hspi->RxXferCount--; + +#if (USE_SPI_CRC != 0U) + /* Enable CRC Transmission */ + if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)) + { + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + + if (hspi->RxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + hspi->RxISR = SPI_RxISR_16BITCRC; + return; + } +#endif /* USE_SPI_CRC */ + SPI_CloseRx_ISR(hspi); + } +} + +/** + * @brief Handle the data 8-bit transmit in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi) +{ + *(__IO uint8_t *)&hspi->Instance->DR = (*hspi->pTxBuffPtr); + hspi->pTxBuffPtr++; + hspi->TxXferCount--; + + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Enable CRC Transmission */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + SPI_CloseTx_ISR(hspi); + } +} + +/** + * @brief Handle the data 16-bit transmit in Interrupt mode. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi) +{ + /* Transmit data in 16 Bit mode */ + hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr); + hspi->pTxBuffPtr += sizeof(uint16_t); + hspi->TxXferCount--; + + if (hspi->TxXferCount == 0U) + { +#if (USE_SPI_CRC != 0U) + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + /* Enable CRC Transmission */ + SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT); + } +#endif /* USE_SPI_CRC */ + SPI_CloseTx_ISR(hspi); + } +} + +/** + * @brief Handle SPI Communication Timeout. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param Flag SPI flag to check + * @param State flag state to check + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State, + uint32_t Timeout, uint32_t Tickstart) +{ + __IO uint32_t count; + uint32_t tmp_timeout; + uint32_t tmp_tickstart; + + /* Adjust Timeout value in case of end of transfer */ + tmp_timeout = Timeout - (HAL_GetTick() - Tickstart); + tmp_tickstart = HAL_GetTick(); + + /* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */ + count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U); + + while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State) + { + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U)) + { + /* Disable the SPI and reset the CRC: the CRC value should be cleared + on both master and slave sides in order to resynchronize the master + and slave for their respective CRC calculation */ + + /* Disable TXE, RXNE and ERR interrupts for the interrupt process */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR)); + + if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE) + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + { + /* Disable SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + } + + /* Reset CRC Calculation */ + if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE) + { + SPI_RESET_CRC(hspi); + } + + hspi->State = HAL_SPI_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(hspi); + + return HAL_TIMEOUT; + } + /* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */ + if (count == 0U) + { + tmp_timeout = 0U; + } + count--; + } + } + + return HAL_OK; +} + +/** + * @brief Handle the check of the RX transaction complete. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart) +{ + if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE) + || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))) + { + /* Disable SPI peripheral */ + __HAL_SPI_DISABLE(hspi); + } + + /* Erratasheet: BSY bit may stay high at the end of a data transfer in Slave mode */ + if (hspi->Init.Mode == SPI_MODE_MASTER) + { + if (hspi->Init.Direction != SPI_DIRECTION_2LINES_RXONLY) + { + /* Control the BSY flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + else + { + /* Wait the RXNE reset */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + } + else + { + /* Wait the RXNE reset */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + return HAL_OK; +} + +/** + * @brief Handle the check of the RXTX or TX transaction complete. + * @param hspi SPI handle + * @param Timeout Timeout duration + * @param Tickstart tick start value + * @retval HAL status + */ +static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart) +{ + /* Timeout in µs */ + __IO uint32_t count = SPI_BSY_FLAG_WORKAROUND_TIMEOUT * (SystemCoreClock / 24U / 1000000U); + /* Erratasheet: BSY bit may stay high at the end of a data transfer in Slave mode */ + if (hspi->Init.Mode == SPI_MODE_MASTER) + { + /* Control the BSY flag */ + if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + return HAL_TIMEOUT; + } + } + else + { + /* Wait BSY flag during 1 Byte time transfer in case of Full-Duplex and Tx transfer + * If Timeout is reached, the transfer is considered as finish. + * User have to calculate the timeout value to fit with the time of 1 byte transfer. + * This time is directly link with the SPI clock from Master device. + */ + do + { + if (count == 0U) + { + break; + } + count--; + } while (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_BSY) != RESET); + } + + return HAL_OK; +} + +/** + * @brief Handle the end of the RXTX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi) +{ + uint32_t tickstart; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + /* Disable ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + hspi->State = HAL_SPI_STATE_READY; + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { +#endif /* USE_SPI_CRC */ + if (hspi->ErrorCode == HAL_SPI_ERROR_NONE) + { + if (hspi->State == HAL_SPI_STATE_BUSY_RX) + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user TxRx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxRxCpltCallback(hspi); +#else + HAL_SPI_TxRxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + } + else + { + hspi->State = HAL_SPI_STATE_READY; + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +#if (USE_SPI_CRC != 0U) + } +#endif /* USE_SPI_CRC */ +} + +/** + * @brief Handle the end of the RX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi) +{ + /* Disable RXNE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR)); + + /* Check the end of the transaction */ + if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + hspi->State = HAL_SPI_STATE_READY; + +#if (USE_SPI_CRC != 0U) + /* Check if CRC error occurred */ + if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC); + __HAL_SPI_CLEAR_CRCERRFLAG(hspi); + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { +#endif /* USE_SPI_CRC */ + if (hspi->ErrorCode == HAL_SPI_ERROR_NONE) + { + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->RxCpltCallback(hspi); +#else + HAL_SPI_RxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +#if (USE_SPI_CRC != 0U) + } +#endif /* USE_SPI_CRC */ +} + +/** + * @brief Handle the end of the TX transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi) +{ + uint32_t tickstart; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Init tickstart for timeout management*/ + tickstart = HAL_GetTick(); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Disable TXE and ERR interrupt */ + __HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR)); + + /* Check the end of the transaction */ + if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG); + } + + /* Clear overrun flag in 2 Lines communication mode because received is not read */ + if (hspi->Init.Direction == SPI_DIRECTION_2LINES) + { + __HAL_SPI_CLEAR_OVRFLAG(hspi); + } + + hspi->State = HAL_SPI_STATE_READY; + if (hspi->ErrorCode != HAL_SPI_ERROR_NONE) + { + /* Call user error callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->ErrorCallback(hspi); +#else + HAL_SPI_ErrorCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } + else + { + /* Call user Rx complete callback */ +#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U) + hspi->TxCpltCallback(hspi); +#else + HAL_SPI_TxCpltCallback(hspi); +#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Handle abort a Rx transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi) +{ + __IO uint32_t tmpreg = 0U; + __IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U); + + /* Wait until TXE flag is set */ + do + { + if (count == 0U) + { + SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT); + break; + } + count--; + } while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET); + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + /* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE)); + + /* Flush Data Register by a blank read */ + tmpreg = READ_REG(hspi->Instance->DR); + /* To avoid GCC warning */ + UNUSED(tmpreg); + + hspi->State = HAL_SPI_STATE_ABORT; +} + +/** + * @brief Handle abort a Tx or Rx/Tx transaction. + * @param hspi pointer to a SPI_HandleTypeDef structure that contains + * the configuration information for SPI module. + * @retval None + */ +static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi) +{ + /* Disable TXEIE interrupt */ + CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE)); + + /* Disable SPI Peripheral */ + __HAL_SPI_DISABLE(hspi); + + hspi->State = HAL_SPI_STATE_ABORT; +} + +/** + * @} + */ + +#endif /* HAL_SPI_MODULE_ENABLED */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c new file mode 100644 index 0000000..ef2eaf0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sram.c @@ -0,0 +1,1110 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_sram.c + * @author MCD Application Team + * @brief SRAM HAL module driver. + * This file provides a generic firmware to drive SRAM memories + * mounted as external device. + * + ****************************************************************************** + * @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 ##### + ============================================================================== + [..] + This driver is a generic layered driver which contains a set of APIs used to + control SRAM memories. It uses the FMC layer functions to interface + with SRAM devices. + The following sequence should be followed to configure the FMC/FSMC to interface + with SRAM/PSRAM memories: + + (#) Declare a SRAM_HandleTypeDef handle structure, for example: + SRAM_HandleTypeDef hsram; and: + + (++) Fill the SRAM_HandleTypeDef handle "Init" field with the allowed + values of the structure member. + + (++) Fill the SRAM_HandleTypeDef handle "Instance" field with a predefined + base register instance for NOR or SRAM device + + (++) Fill the SRAM_HandleTypeDef handle "Extended" field with a predefined + base register instance for NOR or SRAM extended mode + + (#) Declare two FMC_NORSRAM_TimingTypeDef structures, for both normal and extended + mode timings; for example: + FMC_NORSRAM_TimingTypeDef Timing and FMC_NORSRAM_TimingTypeDef ExTiming; + and fill its fields with the allowed values of the structure member. + + (#) Initialize the SRAM Controller by calling the function HAL_SRAM_Init(). This function + performs the following sequence: + + (##) MSP hardware layer configuration using the function HAL_SRAM_MspInit() + (##) Control register configuration using the FMC NORSRAM interface function + FMC_NORSRAM_Init() + (##) Timing register configuration using the FMC NORSRAM interface function + FMC_NORSRAM_Timing_Init() + (##) Extended mode Timing register configuration using the FMC NORSRAM interface function + FMC_NORSRAM_Extended_Timing_Init() + (##) Enable the SRAM device using the macro __FMC_NORSRAM_ENABLE() + + (#) At this stage you can perform read/write accesses from/to the memory connected + to the NOR/SRAM Bank. You can perform either polling or DMA transfer using the + following APIs: + (++) HAL_SRAM_Read()/HAL_SRAM_Write() for polling read/write access + (++) HAL_SRAM_Read_DMA()/HAL_SRAM_Write_DMA() for DMA read/write transfer + + (#) You can also control the SRAM device by calling the control APIs HAL_SRAM_WriteOperation_Enable()/ + HAL_SRAM_WriteOperation_Disable() to respectively enable/disable the SRAM write operation + + (#) You can continuously monitor the SRAM device HAL state by calling the function + HAL_SRAM_GetState() + + *** Callback registration *** + ============================================= + [..] + The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + Use Functions HAL_SRAM_RegisterCallback() to register a user callback, + it allows to register following callbacks: + (+) MspInitCallback : SRAM MspInit. + (+) MspDeInitCallback : SRAM MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + Use function HAL_SRAM_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. It allows to reset following callbacks: + (+) MspInitCallback : SRAM MspInit. + (+) MspDeInitCallback : SRAM MspDeInit. + This function) takes as parameters the HAL peripheral handle and the Callback ID. + + By default, after the HAL_SRAM_Init and if the state is HAL_SRAM_STATE_RESET + all callbacks are reset to the corresponding legacy weak (surcharged) functions. + Exception done for MspInit and MspDeInit callbacks that are respectively + reset to the legacy weak (surcharged) functions in the HAL_SRAM_Init + and HAL_SRAM_DeInit only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the HAL_SRAM_Init and HAL_SRAM_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in READY state only. + Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered + in READY or 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_SRAM_RegisterCallback before calling HAL_SRAM_DeInit + or HAL_SRAM_Init function. + + When The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(FMC_Bank1) || defined(FSMC_Bank1) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_SRAM_MODULE_ENABLED + +/** @defgroup SRAM SRAM + * @brief SRAM driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static void SRAM_DMACplt(DMA_HandleTypeDef *hdma); +static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma); +static void SRAM_DMAError(DMA_HandleTypeDef *hdma); + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup SRAM_Exported_Functions SRAM Exported Functions + * @{ + */ + +/** @defgroup SRAM_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions. + * + @verbatim + ============================================================================== + ##### SRAM Initialization and de_initialization functions ##### + ============================================================================== + [..] This section provides functions allowing to initialize/de-initialize + the SRAM memory + +@endverbatim + * @{ + */ + +/** + * @brief Performs the SRAM device initialization sequence + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param Timing Pointer to SRAM control timing structure + * @param ExtTiming Pointer to SRAM extended mode timing structure + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram, FMC_NORSRAM_TimingTypeDef *Timing, + FMC_NORSRAM_TimingTypeDef *ExtTiming) +{ + /* Check the SRAM handle parameter */ + if (hsram == NULL) + { + return HAL_ERROR; + } + + if (hsram->State == HAL_SRAM_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + hsram->Lock = HAL_UNLOCKED; + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + if (hsram->MspInitCallback == NULL) + { + hsram->MspInitCallback = HAL_SRAM_MspInit; + } + hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback; + hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback; + + /* Init the low level hardware */ + hsram->MspInitCallback(hsram); +#else + /* Initialize the low level hardware (MSP) */ + HAL_SRAM_MspInit(hsram); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ + } + + /* Initialize SRAM control Interface */ + (void)FMC_NORSRAM_Init(hsram->Instance, &(hsram->Init)); + + /* Initialize SRAM timing Interface */ + (void)FMC_NORSRAM_Timing_Init(hsram->Instance, Timing, hsram->Init.NSBank); + + /* Initialize SRAM extended mode timing Interface */ + (void)FMC_NORSRAM_Extended_Timing_Init(hsram->Extended, ExtTiming, hsram->Init.NSBank, + hsram->Init.ExtendedMode); + + /* Enable the NORSRAM device */ + __FMC_NORSRAM_ENABLE(hsram->Instance, hsram->Init.NSBank); + + /* Initialize the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + + return HAL_OK; +} + +/** + * @brief Performs the SRAM device De-initialization sequence. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_DeInit(SRAM_HandleTypeDef *hsram) +{ +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + if (hsram->MspDeInitCallback == NULL) + { + hsram->MspDeInitCallback = HAL_SRAM_MspDeInit; + } + + /* DeInit the low level hardware */ + hsram->MspDeInitCallback(hsram); +#else + /* De-Initialize the low level hardware (MSP) */ + HAL_SRAM_MspDeInit(hsram); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ + + /* Configure the SRAM registers with their reset values */ + (void)FMC_NORSRAM_DeInit(hsram->Instance, hsram->Extended, hsram->Init.NSBank); + + /* Reset the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(hsram); + + return HAL_OK; +} + +/** + * @brief SRAM MSP Init. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval None + */ +__weak void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsram); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SRAM_MspInit could be implemented in the user file + */ +} + +/** + * @brief SRAM MSP DeInit. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval None + */ +__weak void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hsram); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SRAM_MspDeInit could be implemented in the user file + */ +} + +/** + * @brief DMA transfer complete callback. + * @param hdma pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval None + */ +__weak void HAL_SRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SRAM_DMA_XferCpltCallback could be implemented in the user file + */ +} + +/** + * @brief DMA transfer complete error callback. + * @param hdma pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval None + */ +__weak void HAL_SRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hdma); + + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_SRAM_DMA_XferErrorCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** @defgroup SRAM_Exported_Functions_Group2 Input Output and memory control functions + * @brief Input Output and memory control functions + * + @verbatim + ============================================================================== + ##### SRAM Input and Output functions ##### + ============================================================================== + [..] + This section provides functions allowing to use and control the SRAM memory + +@endverbatim + * @{ + */ + +/** + * @brief Reads 8-bit buffer from SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint8_t *psramaddress = (uint8_t *)pAddress; + uint8_t *pdestbuff = pDstBuffer; + HAL_SRAM_StateTypeDef state = hsram->State; + + /* Check the SRAM controller state */ + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Read data from memory */ + for (size = BufferSize; size != 0U; size--) + { + *pdestbuff = *psramaddress; + pdestbuff++; + psramaddress++; + } + + /* Update the SRAM controller state */ + hsram->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 8-bit buffer to SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint8_t *psramaddress = (uint8_t *)pAddress; + uint8_t *psrcbuff = pSrcBuffer; + + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Write data to memory */ + for (size = BufferSize; size != 0U; size--) + { + *psramaddress = *psrcbuff; + psrcbuff++; + psramaddress++; + } + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads 16-bit buffer from SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *psramaddress = pAddress; + uint16_t *pdestbuff = pDstBuffer; + uint8_t limit; + HAL_SRAM_StateTypeDef state = hsram->State; + + /* Check the SRAM controller state */ + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Check if the size is a 32-bits multiple */ + limit = (((BufferSize % 2U) != 0U) ? 1U : 0U); + + /* Read data from memory */ + for (size = BufferSize; size != limit; size -= 2U) + { + *pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU); + pdestbuff++; + *pdestbuff = (uint16_t)(((*psramaddress) & 0xFFFF0000U) >> 16U); + pdestbuff++; + psramaddress++; + } + + /* Read last 16-bits if size is not 32-bits multiple */ + if (limit != 0U) + { + *pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU); + } + + /* Update the SRAM controller state */ + hsram->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 16-bit buffer to SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *psramaddress = pAddress; + uint16_t *psrcbuff = pSrcBuffer; + uint8_t limit; + + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Check if the size is a 32-bits multiple */ + limit = (((BufferSize % 2U) != 0U) ? 1U : 0U); + + /* Write data to memory */ + for (size = BufferSize; size != limit; size -= 2U) + { + *psramaddress = (uint32_t)(*psrcbuff); + psrcbuff++; + *psramaddress |= ((uint32_t)(*psrcbuff) << 16U); + psrcbuff++; + psramaddress++; + } + + /* Write last 16-bits if size is not 32-bits multiple */ + if (limit != 0U) + { + *psramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psramaddress) & 0xFFFF0000U); + } + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads 32-bit buffer from SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *psramaddress = pAddress; + uint32_t *pdestbuff = pDstBuffer; + HAL_SRAM_StateTypeDef state = hsram->State; + + /* Check the SRAM controller state */ + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Read data from memory */ + for (size = BufferSize; size != 0U; size--) + { + *pdestbuff = *psramaddress; + pdestbuff++; + psramaddress++; + } + + /* Update the SRAM controller state */ + hsram->State = state; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Writes 32-bit buffer to SRAM memory. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize) +{ + uint32_t size; + __IO uint32_t *psramaddress = pAddress; + uint32_t *psrcbuff = pSrcBuffer; + + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Write data to memory */ + for (size = BufferSize; size != 0U; size--) + { + *psramaddress = *psrcbuff; + psrcbuff++; + psramaddress++; + } + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Reads a Words data from the SRAM memory using DMA transfer. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to read start address + * @param pDstBuffer Pointer to destination buffer + * @param BufferSize Size of the buffer to read from memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer, + uint32_t BufferSize) +{ + HAL_StatusTypeDef status; + HAL_SRAM_StateTypeDef state = hsram->State; + + /* Check the SRAM controller state */ + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Configure DMA user callbacks */ + if (state == HAL_SRAM_STATE_READY) + { + hsram->hdma->XferCpltCallback = SRAM_DMACplt; + } + else + { + hsram->hdma->XferCpltCallback = SRAM_DMACpltProt; + } + hsram->hdma->XferErrorCallback = SRAM_DMAError; + + /* Enable the DMA Stream */ + status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)BufferSize); + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Writes a Words data buffer to SRAM memory using DMA transfer. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @param pAddress Pointer to write start address + * @param pSrcBuffer Pointer to source buffer to write + * @param BufferSize Size of the buffer to write to memory + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer, + uint32_t BufferSize) +{ + HAL_StatusTypeDef status; + + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Configure DMA user callbacks */ + hsram->hdma->XferCpltCallback = SRAM_DMACplt; + hsram->hdma->XferErrorCallback = SRAM_DMAError; + + /* Enable the DMA Stream */ + status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)BufferSize); + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + status = HAL_ERROR; + } + + return status; +} + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User SRAM Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hsram : SRAM handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID + * @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SRAM_RegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId, + pSRAM_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SRAM_StateTypeDef state; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hsram); + + state = hsram->State; + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_RESET) || (state == HAL_SRAM_STATE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SRAM_MSP_INIT_CB_ID : + hsram->MspInitCallback = pCallback; + break; + case HAL_SRAM_MSP_DEINIT_CB_ID : + hsram->MspDeInitCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsram); + return status; +} + +/** + * @brief Unregister a User SRAM Callback + * SRAM Callback is redirected to the weak (surcharged) predefined callback + * @param hsram : SRAM handle + * @param CallbackId : ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID + * @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID + * @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID + * @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_SRAM_UnRegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SRAM_StateTypeDef state; + + /* Process locked */ + __HAL_LOCK(hsram); + + state = hsram->State; + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SRAM_MSP_INIT_CB_ID : + hsram->MspInitCallback = HAL_SRAM_MspInit; + break; + case HAL_SRAM_MSP_DEINIT_CB_ID : + hsram->MspDeInitCallback = HAL_SRAM_MspDeInit; + break; + case HAL_SRAM_DMA_XFER_CPLT_CB_ID : + hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback; + break; + case HAL_SRAM_DMA_XFER_ERR_CB_ID : + hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else if (state == HAL_SRAM_STATE_RESET) + { + switch (CallbackId) + { + case HAL_SRAM_MSP_INIT_CB_ID : + hsram->MspInitCallback = HAL_SRAM_MspInit; + break; + case HAL_SRAM_MSP_DEINIT_CB_ID : + hsram->MspDeInitCallback = HAL_SRAM_MspDeInit; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsram); + return status; +} + +/** + * @brief Register a User SRAM Callback for DMA transfers + * To be used instead of the weak (surcharged) predefined callback + * @param hsram : SRAM handle + * @param CallbackId : ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID + * @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID + * @param pCallback : pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_SRAM_RegisterDmaCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId, + pSRAM_DmaCallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + HAL_SRAM_StateTypeDef state; + + if (pCallback == NULL) + { + return HAL_ERROR; + } + + /* Process locked */ + __HAL_LOCK(hsram); + + state = hsram->State; + if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED)) + { + switch (CallbackId) + { + case HAL_SRAM_DMA_XFER_CPLT_CB_ID : + hsram->DmaXferCpltCallback = pCallback; + break; + case HAL_SRAM_DMA_XFER_ERR_CB_ID : + hsram->DmaXferErrorCallback = pCallback; + break; + default : + /* update return status */ + status = HAL_ERROR; + break; + } + } + else + { + /* update return status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(hsram); + return status; +} +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup SRAM_Exported_Functions_Group3 Control functions + * @brief Control functions + * +@verbatim + ============================================================================== + ##### SRAM Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the SRAM interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically SRAM write operation. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_WriteOperation_Enable(SRAM_HandleTypeDef *hsram) +{ + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_PROTECTED) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Enable write operation */ + (void)FMC_NORSRAM_WriteOperation_Enable(hsram->Instance, hsram->Init.NSBank); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically SRAM write operation. + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_SRAM_WriteOperation_Disable(SRAM_HandleTypeDef *hsram) +{ + /* Check the SRAM controller state */ + if (hsram->State == HAL_SRAM_STATE_READY) + { + /* Process Locked */ + __HAL_LOCK(hsram); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_BUSY; + + /* Disable write operation */ + (void)FMC_NORSRAM_WriteOperation_Disable(hsram->Instance, hsram->Init.NSBank); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_PROTECTED; + + /* Process unlocked */ + __HAL_UNLOCK(hsram); + } + else + { + return HAL_ERROR; + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup SRAM_Exported_Functions_Group4 Peripheral State functions + * @brief Peripheral State functions + * +@verbatim + ============================================================================== + ##### SRAM State functions ##### + ============================================================================== + [..] + This subsection permits to get in run-time the status of the SRAM controller + and the data flow. + +@endverbatim + * @{ + */ + +/** + * @brief Returns the SRAM controller state + * @param hsram pointer to a SRAM_HandleTypeDef structure that contains + * the configuration information for SRAM module. + * @retval HAL state + */ +HAL_SRAM_StateTypeDef HAL_SRAM_GetState(SRAM_HandleTypeDef *hsram) +{ + return hsram->State; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @brief DMA SRAM process complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void SRAM_DMACplt(DMA_HandleTypeDef *hdma) +{ + SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_READY; + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + hsram->DmaXferCpltCallback(hdma); +#else + HAL_SRAM_DMA_XferCpltCallback(hdma); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SRAM process complete callback. + * @param hdma : DMA handle + * @retval None + */ +static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma) +{ + SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_PROTECTED; + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + hsram->DmaXferCpltCallback(hdma); +#else + HAL_SRAM_DMA_XferCpltCallback(hdma); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA SRAM error callback. + * @param hdma : DMA handle + * @retval None + */ +static void SRAM_DMAError(DMA_HandleTypeDef *hdma) +{ + SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent); + + /* Disable the DMA channel */ + __HAL_DMA_DISABLE(hdma); + + /* Update the SRAM controller state */ + hsram->State = HAL_SRAM_STATE_ERROR; + +#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1) + hsram->DmaXferErrorCallback(hdma); +#else + HAL_SRAM_DMA_XferErrorCallback(hdma); +#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */ +} + +/** + * @} + */ + +#endif /* HAL_SRAM_MODULE_ENABLED */ + +/** + * @} + */ + +#endif /* FMC_Bank1 || FSMC_Bank1 */ diff --git a/libs/hal/stm32f4xx_hal_tim.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c similarity index 99% rename from libs/hal/stm32f4xx_hal_tim.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c index 1ca1781..e35049b 100644 --- a/libs/hal/stm32f4xx_hal_tim.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim.c @@ -204,9 +204,9 @@ all interrupt callbacks are set to the corresponding weak functions: /** @addtogroup TIM_Private_Functions * @{ */ -static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); -static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); -static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config); +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config); static void TIM_TI1_ConfigInputStage(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICFilter); static void TIM_TI2_SetConfig(TIM_TypeDef *TIMx, uint32_t TIM_ICPolarity, uint32_t TIM_ICSelection, uint32_t TIM_ICFilter); @@ -222,7 +222,7 @@ static void TIM_DMADelayPulseCplt(DMA_HandleTypeDef *hdma); static void TIM_DMATriggerCplt(DMA_HandleTypeDef *hdma); static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma); static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, - TIM_SlaveConfigTypeDef *sSlaveConfig); + const TIM_SlaveConfigTypeDef *sSlaveConfig); /** * @} */ @@ -522,7 +522,7 @@ HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim) * @param Length The length of data to be transferred from memory to peripheral. * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length) +HAL_StatusTypeDef HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, const uint32_t *pData, uint16_t Length) { uint32_t tmpsmcr; @@ -1043,7 +1043,8 @@ HAL_StatusTypeDef HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) * @param Length The length of data to be transferred from memory to TIM peripheral * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +HAL_StatusTypeDef HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; @@ -1706,7 +1707,8 @@ HAL_StatusTypeDef HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel) * @param Length The length of data to be transferred from memory to TIM peripheral * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +HAL_StatusTypeDef HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; @@ -4028,7 +4030,7 @@ void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, - TIM_OC_InitTypeDef *sConfig, + const TIM_OC_InitTypeDef *sConfig, uint32_t Channel) { HAL_StatusTypeDef status = HAL_OK; @@ -4106,7 +4108,7 @@ HAL_StatusTypeDef HAL_TIM_OC_ConfigChannel(TIM_HandleTypeDef *htim, * @arg TIM_CHANNEL_4: TIM Channel 4 selected * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitTypeDef *sConfig, uint32_t Channel) +HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, const TIM_IC_InitTypeDef *sConfig, uint32_t Channel) { HAL_StatusTypeDef status = HAL_OK; @@ -4206,7 +4208,7 @@ HAL_StatusTypeDef HAL_TIM_IC_ConfigChannel(TIM_HandleTypeDef *htim, TIM_IC_InitT * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, - TIM_OC_InitTypeDef *sConfig, + const TIM_OC_InitTypeDef *sConfig, uint32_t Channel) { HAL_StatusTypeDef status = HAL_OK; @@ -4468,7 +4470,7 @@ HAL_StatusTypeDef HAL_TIM_OnePulse_ConfigChannel(TIM_HandleTypeDef *htim, TIM_O * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, - uint32_t BurstRequestSrc, uint32_t *BurstBuffer, uint32_t BurstLength) + uint32_t BurstRequestSrc, const uint32_t *BurstBuffer, uint32_t BurstLength) { HAL_StatusTypeDef status; @@ -4520,7 +4522,7 @@ HAL_StatusTypeDef HAL_TIM_DMABurst_WriteStart(TIM_HandleTypeDef *htim, uint32_t * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_DMABurst_MultiWriteStart(TIM_HandleTypeDef *htim, uint32_t BurstBaseAddress, - uint32_t BurstRequestSrc, uint32_t *BurstBuffer, + uint32_t BurstRequestSrc, const uint32_t *BurstBuffer, uint32_t BurstLength, uint32_t DataLength) { HAL_StatusTypeDef status = HAL_OK; @@ -5160,7 +5162,7 @@ HAL_StatusTypeDef HAL_TIM_GenerateEvent(TIM_HandleTypeDef *htim, uint32_t EventS * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, - TIM_ClearInputConfigTypeDef *sClearInputConfig, + const TIM_ClearInputConfigTypeDef *sClearInputConfig, uint32_t Channel) { HAL_StatusTypeDef status = HAL_OK; @@ -5289,7 +5291,7 @@ HAL_StatusTypeDef HAL_TIM_ConfigOCrefClear(TIM_HandleTypeDef *htim, * contains the clock source information for the TIM peripheral. * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, TIM_ClockConfigTypeDef *sClockSourceConfig) +HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, const TIM_ClockConfigTypeDef *sClockSourceConfig) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; @@ -5475,7 +5477,7 @@ HAL_StatusTypeDef HAL_TIM_ConfigTI1Input(TIM_HandleTypeDef *htim, uint32_t TI1_S * (Disable, Reset, Gated, Trigger, External clock mode 1). * @retval HAL status */ -HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, TIM_SlaveConfigTypeDef *sSlaveConfig) +HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, const TIM_SlaveConfigTypeDef *sSlaveConfig) { /* Check the parameters */ assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); @@ -5516,7 +5518,7 @@ HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro(TIM_HandleTypeDef *htim, TIM_SlaveC * @retval HAL status */ HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, - TIM_SlaveConfigTypeDef *sSlaveConfig) + const TIM_SlaveConfigTypeDef *sSlaveConfig) { /* Check the parameters */ assert_param(IS_TIM_SLAVE_INSTANCE(htim->Instance)); @@ -5558,7 +5560,7 @@ HAL_StatusTypeDef HAL_TIM_SlaveConfigSynchro_IT(TIM_HandleTypeDef *htim, * @arg TIM_CHANNEL_4: TIM Channel 4 selected * @retval Captured value */ -uint32_t HAL_TIM_ReadCapturedValue(TIM_HandleTypeDef *htim, uint32_t Channel) +uint32_t HAL_TIM_ReadCapturedValue(const TIM_HandleTypeDef *htim, uint32_t Channel) { uint32_t tmpreg = 0U; @@ -6335,7 +6337,7 @@ HAL_StatusTypeDef HAL_TIM_UnRegisterCallback(TIM_HandleTypeDef *htim, HAL_TIM_Ca * @param htim TIM Base handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6345,7 +6347,7 @@ HAL_TIM_StateTypeDef HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim) * @param htim TIM Output Compare handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6355,7 +6357,7 @@ HAL_TIM_StateTypeDef HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim) * @param htim TIM handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6365,7 +6367,7 @@ HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim) * @param htim TIM IC handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6375,7 +6377,7 @@ HAL_TIM_StateTypeDef HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim) * @param htim TIM OPM handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6385,7 +6387,7 @@ HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim) * @param htim TIM Encoder Interface handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -6395,7 +6397,7 @@ HAL_TIM_StateTypeDef HAL_TIM_Encoder_GetState(TIM_HandleTypeDef *htim) * @param htim TIM handle * @retval Active channel */ -HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(TIM_HandleTypeDef *htim) +HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(const TIM_HandleTypeDef *htim) { return htim->Channel; } @@ -6413,7 +6415,7 @@ HAL_TIM_ActiveChannel HAL_TIM_GetActiveChannel(TIM_HandleTypeDef *htim) * @arg TIM_CHANNEL_6: TIM Channel 6 * @retval TIM Channel state */ -HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(TIM_HandleTypeDef *htim, uint32_t Channel) +HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(const TIM_HandleTypeDef *htim, uint32_t Channel) { HAL_TIM_ChannelStateTypeDef channel_state; @@ -6430,7 +6432,7 @@ HAL_TIM_ChannelStateTypeDef HAL_TIM_GetChannelState(TIM_HandleTypeDef *htim, ui * @param htim TIM handle * @retval DMA burst state */ -HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(TIM_HandleTypeDef *htim) +HAL_TIM_DMABurstStateTypeDef HAL_TIM_DMABurstState(const TIM_HandleTypeDef *htim) { /* Check the parameters */ assert_param(IS_TIM_DMABURST_INSTANCE(htim->Instance)); @@ -6773,7 +6775,7 @@ static void TIM_DMATriggerHalfCplt(DMA_HandleTypeDef *hdma) * @param Structure TIM Base configuration structure * @retval None */ -void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure) +void TIM_Base_SetConfig(TIM_TypeDef *TIMx, const TIM_Base_InitTypeDef *Structure) { uint32_t tmpcr1; tmpcr1 = TIMx->CR1; @@ -6821,7 +6823,7 @@ void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure) * @param OC_Config The output configuration structure * @retval None */ -static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config) { uint32_t tmpccmrx; uint32_t tmpccer; @@ -6896,7 +6898,7 @@ static void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) * @param OC_Config The output configuration structure * @retval None */ -void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config) { uint32_t tmpccmrx; uint32_t tmpccer; @@ -6972,7 +6974,7 @@ void TIM_OC2_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) * @param OC_Config The output configuration structure * @retval None */ -static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config) { uint32_t tmpccmrx; uint32_t tmpccer; @@ -7046,7 +7048,7 @@ static void TIM_OC3_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) * @param OC_Config The output configuration structure * @retval None */ -static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) +static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, const TIM_OC_InitTypeDef *OC_Config) { uint32_t tmpccmrx; uint32_t tmpccer; @@ -7107,7 +7109,7 @@ static void TIM_OC4_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config) * @retval None */ static HAL_StatusTypeDef TIM_SlaveTimer_SetConfig(TIM_HandleTypeDef *htim, - TIM_SlaveConfigTypeDef *sSlaveConfig) + const TIM_SlaveConfigTypeDef *sSlaveConfig) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; diff --git a/libs/hal/stm32f4xx_hal_tim_ex.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c similarity index 99% rename from libs/hal/stm32f4xx_hal_tim_ex.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c index 092175f..98f26f5 100644 --- a/libs/hal/stm32f4xx_hal_tim_ex.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_tim_ex.c @@ -135,7 +135,7 @@ static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t Cha * @param sConfig TIM Hall Sensor configuration structure * @retval HAL status */ -HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, TIM_HallSensor_InitTypeDef *sConfig) +HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig) { TIM_OC_InitTypeDef OC_Config; @@ -866,7 +866,8 @@ HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channe * @param Length The length of data to be transferred from memory to TIM peripheral * @retval HAL status */ -HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; @@ -1347,7 +1348,8 @@ HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Chann * @param Length The length of data to be transferred from memory to TIM peripheral * @retval HAL status */ -HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) +HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData, + uint16_t Length) { HAL_StatusTypeDef status = HAL_OK; uint32_t tmpsmcr; @@ -1960,7 +1962,7 @@ HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint3 * @retval HAL status */ HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, - TIM_MasterConfigTypeDef *sMasterConfig) + const TIM_MasterConfigTypeDef *sMasterConfig) { uint32_t tmpcr2; uint32_t tmpsmcr; @@ -2021,7 +2023,7 @@ HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim, * @retval HAL status */ HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim, - TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig) + const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig) { /* Keep this variable initialized to 0 as it is used to configure BDTR register */ uint32_t tmpbdtr = 0U; @@ -2215,7 +2217,7 @@ __weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim) * @param htim TIM Hall Sensor handle * @retval HAL state */ -HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim) +HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim) { return htim->State; } @@ -2230,7 +2232,7 @@ HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(TIM_HandleTypeDef *htim) * @arg TIM_CHANNEL_3: TIM Channel 3 * @retval TIM Complementary channel state */ -HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(TIM_HandleTypeDef *htim, uint32_t ChannelN) +HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim, uint32_t ChannelN) { HAL_TIM_ChannelStateTypeDef channel_state; diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c new file mode 100644 index 0000000..e13c721 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_alarm_template.c @@ -0,0 +1,318 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_timebase_rtc_alarm_template.c + * @author MCD Application Team + * @brief HAL time base based on the hardware RTC_ALARM Template. + * + * This file override the native HAL time base functions (defined as weak) + * to use the RTC ALARM for time base generation: + * + Intializes the RTC peripheral to increment the seconds registers each 1ms + * + The alarm is configured to assert an interrupt when the RTC reaches 1ms + * + HAL_IncTick is called at each Alarm event and the time is reset to 00:00:00 + * + HSE (default), LSE or LSI can be selected as RTC clock source + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + This file must be copied to the application folder and modified as follows: + (#) Rename it to 'stm32f4xx_hal_timebase_rtc_alarm.c' + (#) Add this file and the RTC HAL drivers to your project and uncomment + HAL_RTC_MODULE_ENABLED define in stm32f4xx_hal_conf.h + + [..] + (@) HAL RTC alarm and HAL RTC wakeup drivers can’t be used with low power modes: + The wake up capability of the RTC may be intrusive in case of prior low power mode + configuration requiring different wake up sources. + Application/Example behavior is no more guaranteed + (@) The stm32f4xx_hal_timebase_tim use is recommended for the Applications/Examples + requiring low power modes + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup HAL_TimeBase_RTC_Alarm_Template HAL TimeBase RTC Alarm Template + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* Uncomment the line below to select the appropriate RTC Clock source for your application: + + RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision. + + RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing + precision. + + RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing + precision. + */ +#define RTC_CLOCK_SOURCE_HSE +/* #define RTC_CLOCK_SOURCE_LSE */ +/* #define RTC_CLOCK_SOURCE_LSI */ + +#ifdef RTC_CLOCK_SOURCE_HSE + #define RTC_ASYNCH_PREDIV 99U + #define RTC_SYNCH_PREDIV 9U + #define RCC_RTCCLKSOURCE_1MHZ ((uint32_t)((uint32_t)RCC_BDCR_RTCSEL | (uint32_t)((HSE_VALUE/1000000U) << 16U))) +#else /* RTC_CLOCK_SOURCE_LSE || RTC_CLOCK_SOURCE_LSI */ + #define RTC_ASYNCH_PREDIV 0U + #define RTC_SYNCH_PREDIV 31U +#endif /* RTC_CLOCK_SOURCE_HSE */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +RTC_HandleTypeDef hRTC_Handle; +/* Private function prototypes -----------------------------------------------*/ +void RTC_Alarm_IRQHandler(void); +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief This function configures the RTC_ALARMA as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority Tick interrupt priority. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority) +{ + __IO uint32_t counter = 0U; + + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + HAL_StatusTypeDef status; + +#ifdef RTC_CLOCK_SOURCE_LSE + /* Configue LSE as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; +#elif defined (RTC_CLOCK_SOURCE_LSI) + /* Configue LSI as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; +#elif defined (RTC_CLOCK_SOURCE_HSE) + /* Configue HSE as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + /* Ensure that RTC is clocked by 1MHz */ + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_1MHZ; +#else +#error Please select the RTC Clock source +#endif /* RTC_CLOCK_SOURCE_LSE */ + + status = HAL_RCC_OscConfig(&RCC_OscInitStruct); + if (status == HAL_OK) + { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; + status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + } + if (status == HAL_OK) + { + /* Enable RTC Clock */ + __HAL_RCC_RTC_ENABLE(); + /* The time base should be 1ms + Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK + HSE as RTC clock + Time base = ((99 + 1) * (9 + 1)) / 1MHz + = 1ms + LSE as RTC clock + Time base = ((31 + 1) * (0 + 1)) / 32.768KHz + = ~1ms + LSI as RTC clock + Time base = ((31 + 1) * (0 + 1)) / 32KHz + = 1ms + */ + hRTC_Handle.Instance = RTC; + hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24; + hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; + hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV; + hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE; + hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + status = HAL_RTC_Init(&hRTC_Handle); + } + if (status == HAL_OK) + { + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + + /* Disable the Alarm A interrupt */ + __HAL_RTC_ALARMA_DISABLE(&hRTC_Handle); + + /* Clear flag alarm A */ + __HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF); + + counter = 0U; + /* Wait till RTC ALRAWF flag is set and if Time out is reached exit */ + while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAWF) == RESET) + { + if (counter++ == (SystemCoreClock / 48U)) /* Timeout = ~ 1s */ + { + status = HAL_ERROR; + } + } + } + if (status == HAL_OK) + { + hRTC_Handle.Instance->ALRMAR = (uint32_t)0x01U; + + /* Configure the Alarm state: Enable Alarm */ + __HAL_RTC_ALARMA_ENABLE(&hRTC_Handle); + /* Configure the Alarm interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA); + + /* RTC Alarm Interrupt Configuration: EXTI configuration */ + __HAL_RTC_ALARM_EXTI_ENABLE_IT(); + __HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE(); + + /* Check if the Initialization mode is set */ + if ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + /* Set the Initialization mode */ + hRTC_Handle.Instance->ISR = (uint32_t)RTC_INIT_MASK; + counter = 0U; + while ((hRTC_Handle.Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + if (counter++ == (SystemCoreClock / 48U)) /* Timeout = ~ 1s */ + { + status = HAL_ERROR; + } + } + } + } + if (status == HAL_OK) + { + hRTC_Handle.Instance->DR = 0U; + hRTC_Handle.Instance->TR = 0U; + + hRTC_Handle.Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); + + /* Enable the RTC Alarm Interrupt */ + HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn); + + /* Configure the SysTick IRQ priority */ + if (TickPriority < (1UL << __NVIC_PRIO_BITS)) + { + HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority, 0U); + uwTickPrio = TickPriority; + } + else + { + status = HAL_ERROR; + } + + } + return status; +} + +/** + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling RTC ALARM interrupt. + * @retval None + */ +void HAL_SuspendTick(void) +{ + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + /* Disable RTC ALARM update Interrupt */ + __HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA); + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); +} + +/** + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling RTC ALARM interrupt. + * @retval None + */ +void HAL_ResumeTick(void) +{ + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + /* Enable RTC ALARM Update interrupt */ + __HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA); + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); +} + +/** + * @brief ALARM A Event Callback in non blocking mode + * @note This function is called when RTC_ALARM interrupt took place, inside + * RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param hrtc RTC handle + * @retval None + */ +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) +{ + __IO uint32_t counter = 0U; + + HAL_IncTick(); + + __HAL_RTC_WRITEPROTECTION_DISABLE(hrtc); + + /* Set the Initialization mode */ + hrtc->Instance->ISR = (uint32_t)RTC_INIT_MASK; + + while((hrtc->Instance->ISR & RTC_ISR_INITF) == (uint32_t)RESET) + { + if(counter++ == (SystemCoreClock /48U)) /* Timeout = ~ 1s */ + { + break; + } + } + + hrtc->Instance->DR = 0U; + hrtc->Instance->TR = 0U; + + hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(hrtc); +} + +/** + * @brief This function handles RTC ALARM interrupt request. + * @retval None + */ +void RTC_Alarm_IRQHandler(void) +{ + HAL_RTC_AlarmIRQHandler(&hRTC_Handle); +} + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c new file mode 100644 index 0000000..50f9d7f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_rtc_wakeup_template.c @@ -0,0 +1,293 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_timebase_rtc_wakeup_template.c + * @author MCD Application Team + * @brief HAL time base based on the hardware RTC_WAKEUP Template. + * + * This file overrides the native HAL time base functions (defined as weak) + * to use the RTC WAKEUP for the time base generation: + * + Intializes the RTC peripheral and configures the wakeup timer to be + * incremented each 1ms + * + The wakeup feature is configured to assert an interrupt each 1ms + * + HAL_IncTick is called inside the HAL_RTCEx_WakeUpTimerEventCallback + * + HSE (default), LSE or LSI can be selected as RTC clock source + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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 ##### + ============================================================================== + [..] + This file must be copied to the application folder and modified as follows: + (#) Rename it to 'stm32f4xx_hal_timebase_rtc_wakeup.c' + (#) Add this file and the RTC HAL drivers to your project and uncomment + HAL_RTC_MODULE_ENABLED define in stm32f4xx_hal_conf.h + + [..] + (@) HAL RTC alarm and HAL RTC wakeup drivers can’t be used with low power modes: + The wake up capability of the RTC may be intrusive in case of prior low power mode + configuration requiring different wake up sources. + Application/Example behavior is no more guaranteed + (@) The stm32f4xx_hal_timebase_tim use is recommended for the Applications/Examples + requiring low power modes + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup HAL_TimeBase_RTC_WakeUp_Template HAL TimeBase RTC WakeUp Template + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/* Uncomment the line below to select the appropriate RTC Clock source for your application: + + RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision. + + RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing + precision. + + RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing + precision. + */ +#define RTC_CLOCK_SOURCE_HSE +/* #define RTC_CLOCK_SOURCE_LSE */ +/* #define RTC_CLOCK_SOURCE_LSI */ + +#ifdef RTC_CLOCK_SOURCE_HSE + #define RTC_ASYNCH_PREDIV 99U + #define RTC_SYNCH_PREDIV 9U + #define RCC_RTCCLKSOURCE_1MHZ ((uint32_t)((uint32_t)RCC_BDCR_RTCSEL | (uint32_t)((HSE_VALUE/1000000U) << 16U))) +#else /* RTC_CLOCK_SOURCE_LSE || RTC_CLOCK_SOURCE_LSI */ + #define RTC_ASYNCH_PREDIV 0U + #define RTC_SYNCH_PREDIV 31U +#endif /* RTC_CLOCK_SOURCE_HSE */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +RTC_HandleTypeDef hRTC_Handle; + +/* Private function prototypes -----------------------------------------------*/ +void RTC_WKUP_IRQHandler(void); + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief This function configures the RTC_WKUP as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * Wakeup Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK + = 1ms + * Wakeup Time = WakeupTimebase * WakeUpCounter (0 + 1) + = 1 ms + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority Tick interrupt priority. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) +{ + __IO uint32_t counter = 0U; + + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct; + HAL_StatusTypeDef status; + +#ifdef RTC_CLOCK_SOURCE_LSE + /* Configue LSE as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; +#elif defined (RTC_CLOCK_SOURCE_LSI) + /* Configue LSI as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; +#elif defined (RTC_CLOCK_SOURCE_HSE) + /* Configue HSE as RTC clock soucre */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + /* Ensure that RTC is clocked by 1MHz */ + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_1MHZ; +#else +#error Please select the RTC Clock source +#endif /* RTC_CLOCK_SOURCE_LSE */ + + status = HAL_RCC_OscConfig(&RCC_OscInitStruct); + if (status == HAL_OK) + { + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; + status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); + } + if (status == HAL_OK) + { + /* Enable RTC Clock */ + __HAL_RCC_RTC_ENABLE(); + /* The time base should be 1ms + Time base = ((RTC_ASYNCH_PREDIV + 1) * (RTC_SYNCH_PREDIV + 1)) / RTC_CLOCK + HSE as RTC clock + Time base = ((99 + 1) * (9 + 1)) / 1Mhz + = 1ms + LSE as RTC clock + Time base = ((31 + 1) * (0 + 1)) / 32.768Khz + = ~1ms + LSI as RTC clock + Time base = ((31 + 1) * (0 + 1)) / 32Khz + = 1ms + */ + hRTC_Handle.Instance = RTC; + hRTC_Handle.Init.HourFormat = RTC_HOURFORMAT_24; + hRTC_Handle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; + hRTC_Handle.Init.SynchPrediv = RTC_SYNCH_PREDIV; + hRTC_Handle.Init.OutPut = RTC_OUTPUT_DISABLE; + hRTC_Handle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; + hRTC_Handle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; + status = HAL_RTC_Init(&hRTC_Handle); + } + if (status == HAL_OK) + { + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + + /* Disable the Wake-up Timer */ + __HAL_RTC_WAKEUPTIMER_DISABLE(&hRTC_Handle); + + /* In case of interrupt mode is used, the interrupt source must disabled */ + __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT); + + /* Wait till RTC WUTWF flag is set */ + while (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hRTC_Handle, RTC_FLAG_WUTWF) == RESET) + { + if (counter++ == (SystemCoreClock / 48U)) + { + status = HAL_ERROR; + } + } + } + if (status == HAL_OK) + { + /* Clear PWR wake up Flag */ + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + + /* Clear RTC Wake Up timer Flag */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_WUTF); + + /* Configure the Wake-up Timer counter */ + hRTC_Handle.Instance->WUTR = 0U; + + /* Clear the Wake-up Timer clock source bits in CR register */ + hRTC_Handle.Instance->CR &= (uint32_t)~RTC_CR_WUCKSEL; + + /* Configure the clock source */ + hRTC_Handle.Instance->CR |= (uint32_t)RTC_WAKEUPCLOCK_CK_SPRE_16BITS; + + /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */ + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_IT(); + + __HAL_RTC_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE(); + + /* Configure the Interrupt in the RTC_CR register */ + __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle,RTC_IT_WUT); + + /* Enable the Wake-up Timer */ + __HAL_RTC_WAKEUPTIMER_ENABLE(&hRTC_Handle); + + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); + + /* Enable the RTC global Interrupt */ + HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); + + /* Configure the SysTick IRQ priority */ + if (TickPriority < (1UL << __NVIC_PRIO_BITS)) + { + HAL_NVIC_SetPriority(RTC_WKUP_IRQn, TickPriority, 0U); + uwTickPrio = TickPriority; + } + else + { + status = HAL_ERROR; + } + } + return status; +} + +/** + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling RTC_WKUP interrupt. + * @retval None + */ +void HAL_SuspendTick(void) +{ + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + /* Disable WAKE UP TIMER Interrupt */ + __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&hRTC_Handle, RTC_IT_WUT); + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); +} + +/** + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling RTC_WKUP interrupt. + * @retval None + */ +void HAL_ResumeTick(void) +{ + /* Disable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle); + /* Enable WAKE UP TIMER interrupt */ + __HAL_RTC_WAKEUPTIMER_ENABLE_IT(&hRTC_Handle, RTC_IT_WUT); + /* Enable the write protection for RTC registers */ + __HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle); +} + +/** + * @brief Wake Up Timer Event Callback in non blocking mode + * @note This function is called when RTC_WKUP interrupt took place, inside + * RTC_WKUP_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param hrtc RTC handle + * @retval None + */ +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + HAL_IncTick(); +} + +/** + * @brief This function handles WAKE UP TIMER interrupt request. + * @retval None + */ +void RTC_WKUP_IRQHandler(void) +{ + HAL_RTCEx_WakeUpTimerIRQHandler(&hRTC_Handle); +} + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c new file mode 100644 index 0000000..affb884 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_timebase_tim_template.c @@ -0,0 +1,177 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_timebase_tim_template.c + * @author MCD Application Team + * @brief HAL time base based on the hardware TIM Template. + * + * This file overrides the native HAL time base functions (defined as weak) + * the TIM time base: + * + Intializes the TIM peripheral generate a Period elapsed Event each 1ms + * + HAL_IncTick is called inside HAL_TIM_PeriodElapsedCallback ie each 1ms + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup HAL_TimeBase_TIM + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +TIM_HandleTypeDef TimHandle; +/* Private function prototypes -----------------------------------------------*/ +void TIM6_DAC_IRQHandler(void); +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief This function configures the TIM6 as a time base source. + * The time source is configured to have 1ms time base with a dedicated + * Tick interrupt priority. + * @note This function is called automatically at the beginning of program after + * reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig(). + * @param TickPriority Tick interrupt priority. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) +{ + RCC_ClkInitTypeDef clkconfig; + uint32_t uwTimclock, uwAPB1Prescaler = 0U; + uint32_t uwPrescalerValue = 0U; + uint32_t pFLatency; + HAL_StatusTypeDef status; + + /* Enable TIM6 clock */ + __HAL_RCC_TIM6_CLK_ENABLE(); + + /* Get clock configuration */ + HAL_RCC_GetClockConfig(&clkconfig, &pFLatency); + + /* Get APB1 prescaler */ + uwAPB1Prescaler = clkconfig.APB1CLKDivider; + + /* Compute TIM6 clock */ + if (uwAPB1Prescaler == RCC_HCLK_DIV1) + { + uwTimclock = HAL_RCC_GetPCLK1Freq(); + } + else + { + uwTimclock = 2 * HAL_RCC_GetPCLK1Freq(); + } + + /* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */ + uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U); + + /* Initialize TIM6 */ + TimHandle.Instance = TIM6; + + /* Initialize TIMx peripheral as follow: + + Period = [(TIM6CLK/1000) - 1]. to have a (1/1000) s time base. + + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock. + + ClockDivision = 0 + + Counter direction = Up + */ + TimHandle.Init.Period = (1000000U / 1000U) - 1U; + TimHandle.Init.Prescaler = uwPrescalerValue; + TimHandle.Init.ClockDivision = 0U; + TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; + TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + status = HAL_TIM_Base_Init(&TimHandle); + if (status == HAL_OK) + { + /* Start the TIM time Base generation in interrupt mode */ + status = HAL_TIM_Base_Start_IT(&TimHandle); + if (status == HAL_OK) + { + /* Enable the TIM6 global Interrupt */ + HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); + + if (TickPriority < (1UL << __NVIC_PRIO_BITS)) + { + /* Enable the TIM6 global Interrupt */ + HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority, 0); + uwTickPrio = TickPriority; + } + else + { + status = HAL_ERROR; + } + } + } + + /* Return function status */ + return status; +} + +/** + * @brief Suspend Tick increment. + * @note Disable the tick increment by disabling TIM6 update interrupt. + * @retval None + */ +void HAL_SuspendTick(void) +{ + /* Disable TIM6 update Interrupt */ + __HAL_TIM_DISABLE_IT(&TimHandle, TIM_IT_UPDATE); +} + +/** + * @brief Resume Tick increment. + * @note Enable the tick increment by Enabling TIM6 update interrupt. + * @retval None + */ +void HAL_ResumeTick(void) +{ + /* Enable TIM6 Update interrupt */ + __HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE); +} + +/** + * @brief Period elapsed callback in non blocking mode + * @note This function is called when TIM6 interrupt took place, inside + * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment + * a global variable "uwTick" used as application time base. + * @param htim TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + HAL_IncTick(); +} + +/** + * @brief This function handles TIM interrupt request. + * @retval None + */ +void TIM6_DAC_IRQHandler(void) +{ + HAL_TIM_IRQHandler(&TimHandle); +} + +/** + * @} + */ + +/** + * @} + */ + + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c new file mode 100644 index 0000000..e2af538 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_uart.c @@ -0,0 +1,3759 @@ +/** + ****************************************************************************** + * @file stm32f4xx_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 stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required + Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx stream. + (+++) 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 stream. + (+++) 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 "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_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 manual + (RM0430 for STM32F4X3xx MCUs and RM0402 for STM32F412xx MCUs + RM0383 for STM32F411xC/E MCUs and RM0401 for STM32F410xx MCUs + RM0090 for STM32F4X5xx/STM32F4X7xx/STM32F429xx/STM32F439xx MCUs + RM0390 for STM32F446xx MCUs and RM0386 for STM32F469xx/STM32F479xx 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, USART3 and USART6. + Except for STM32F446xx devices, that is available for USART1, USART2, USART3, USART6, UART4 and UART5. + */ + 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)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + 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)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + 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)); + assert_param(IS_UART_LIN_OVERSAMPLING(huart->Init.OverSampling)); + + 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)); + assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + + 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 + * @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; + } + /* Process locked */ + __HAL_LOCK(huart); + + 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; + } + + /* Release Lock */ + __HAL_UNLOCK(huart); + + return status; +} + +/** + * @brief Unregister an UART Callback + * UART callaback is redirected to the weak predefined callback + * @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; + + /* Process locked */ + __HAL_LOCK(huart); + + 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; + } + + /* Release Lock */ + __HAL_UNLOCK(huart); + + 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) + { + 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) + { + 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) + { + 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 stream */ + 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 stream */ + 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 stream */ + 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 (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 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 stream: 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 stream: 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 stream : 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 stream : 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 stream : 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 stream : 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 stream : 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 stream : 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 stream */ + 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->CR & DMA_SxCR_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->CR & DMA_SxCR_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 ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); + ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_TIMEOUT; + } + } + } + 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 */ + + 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); + + /*-------------------------- 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 defined(USART6) && defined(UART9) && defined(UART10) + if ((huart->Instance == USART1) || (huart->Instance == USART6) || (huart->Instance == UART9) || (huart->Instance == UART10)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + } +#elif defined(USART6) + if ((huart->Instance == USART1) || (huart->Instance == USART6)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + } +#else + if (huart->Instance == USART1) + { + pclk = HAL_RCC_GetPCLK2Freq(); + } +#endif /* USART6 */ + else + { + pclk = HAL_RCC_GetPCLK1Freq(); + } + /*-------------------------- USART BRR Configuration ---------------------*/ + 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); + } +} + +/** + * @} + */ + +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c new file mode 100644 index 0000000..b6df8e7 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_usart.c @@ -0,0 +1,2838 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_usart.c + * @author MCD Application Team + * @brief USART HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Universal Synchronous/Asynchronous Receiver Transmitter + * Peripheral (USART). + * + Initialization and de-initialization functions + * + IO operation functions + * + Peripheral Control 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 USART HAL driver can be used as follows: + + (#) Declare a USART_HandleTypeDef handle structure (eg. USART_HandleTypeDef husart). + (#) Initialize the USART low level resources by implementing the HAL_USART_MspInit() API: + (##) Enable the USARTx interface clock. + (##) USART pins configuration: + (+++) Enable the clock for the USART GPIOs. + (+++) Configure the USART pins as alternate function pull-up. + (##) NVIC configuration if you need to use interrupt process (HAL_USART_Transmit_IT(), + HAL_USART_Receive_IT() and HAL_USART_TransmitReceive_IT() APIs): + (+++) Configure the USARTx interrupt priority. + (+++) Enable the NVIC USART IRQ handle. + (##) DMA Configuration if you need to use DMA process (HAL_USART_Transmit_DMA() + HAL_USART_Receive_DMA() and HAL_USART_TransmitReceive_DMA() APIs): + (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) Enable the DMAx interface clock. + (+++) Configure the declared DMA handle structure with the required Tx/Rx parameters. + (+++) Configure the DMA Tx/Rx stream. + (+++) Associate the initialized DMA handle to the USART DMA Tx/Rx handle. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx stream. + (+++) 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 husart Init structure. + + (#) Initialize the USART registers by calling the HAL_USART_Init() API: + (++) These APIs configures also the low level Hardware GPIO, CLOCK, CORTEX...etc) + by calling the customized HAL_USART_MspInit(&husart) API. + + -@@- The specific USART interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) will be managed using the macros + __HAL_USART_ENABLE_IT() and __HAL_USART_DISABLE_IT() inside the transmit and receive process. + + (#) Three operation modes are available within this driver : + + *** Polling mode IO operation *** + ================================= + [..] + (+) Send an amount of data in blocking mode using HAL_USART_Transmit() + (+) Receive an amount of data in blocking mode using HAL_USART_Receive() + + *** Interrupt mode IO operation *** + =================================== + [..] + (+) Send an amount of data in non blocking mode using HAL_USART_Transmit_IT() + (+) At transmission end of transfer HAL_USART_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_TxCpltCallback + (+) Receive an amount of data in non blocking mode using HAL_USART_Receive_IT() + (+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_RxCpltCallback + (+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_USART_ErrorCallback + + *** DMA mode IO operation *** + ============================== + [..] + (+) Send an amount of data in non blocking mode (DMA) using HAL_USART_Transmit_DMA() + (+) At transmission end of half transfer HAL_USART_TxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_TxHalfCpltCallback + (+) At transmission end of transfer HAL_USART_TxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_TxCpltCallback + (+) Receive an amount of data in non blocking mode (DMA) using HAL_USART_Receive_DMA() + (+) At reception end of half transfer HAL_USART_RxHalfCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_RxHalfCpltCallback + (+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can + add his own code by customization of function pointer HAL_USART_RxCpltCallback + (+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can + add his own code by customization of function pointer HAL_USART_ErrorCallback + (+) Pause the DMA Transfer using HAL_USART_DMAPause() + (+) Resume the DMA Transfer using HAL_USART_DMAResume() + (+) Stop the DMA Transfer using HAL_USART_DMAStop() + + *** USART HAL driver macros list *** + ============================================= + [..] + Below the list of most used macros in USART HAL driver. + + (+) __HAL_USART_ENABLE: Enable the USART peripheral + (+) __HAL_USART_DISABLE: Disable the USART peripheral + (+) __HAL_USART_GET_FLAG : Check whether the specified USART flag is set or not + (+) __HAL_USART_CLEAR_FLAG : Clear the specified USART pending flag + (+) __HAL_USART_ENABLE_IT: Enable the specified USART interrupt + (+) __HAL_USART_DISABLE_IT: Disable the specified USART interrupt + + [..] + (@) You can refer to the USART HAL driver header file for more useful macros + + ##### Callback registration ##### + ================================== + + [..] + The compilation define USE_HAL_USART_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + + [..] + Use Function @ref HAL_USART_RegisterCallback() to register a user callback. + Function @ref HAL_USART_RegisterCallback() allows to register following callbacks: + (+) TxHalfCpltCallback : Tx Half Complete Callback. + (+) TxCpltCallback : Tx Complete Callback. + (+) RxHalfCpltCallback : Rx Half Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) TxRxCpltCallback : Tx Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) MspInitCallback : USART MspInit. + (+) MspDeInitCallback : USART MspDeInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + [..] + Use function @ref HAL_USART_UnRegisterCallback() to reset a callback to the default + weak (surcharged) function. + @ref HAL_USART_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. + (+) TxRxCpltCallback : Tx Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) AbortCpltCallback : Abort Complete Callback. + (+) MspInitCallback : USART MspInit. + (+) MspDeInitCallback : USART MspDeInit. + + [..] + By default, after the @ref HAL_USART_Init() and when the state is HAL_USART_STATE_RESET + all callbacks are set to the corresponding weak (surcharged) functions: + examples @ref HAL_USART_TxCpltCallback(), @ref HAL_USART_RxHalfCpltCallback(). + Exception done for MspInit and MspDeInit functions that are respectively + reset to the legacy weak (surcharged) functions in the @ref HAL_USART_Init() + and @ref HAL_USART_DeInit() only when these callbacks are null (not registered beforehand). + If not, MspInit or MspDeInit are not null, the @ref HAL_USART_Init() and @ref HAL_USART_DeInit() + keep and use the user MspInit/MspDeInit callbacks (registered beforehand). + + [..] + Callbacks can be registered/unregistered in HAL_USART_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_USART_STATE_READY or HAL_USART_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 @ref HAL_USART_RegisterCallback() before calling @ref HAL_USART_DeInit() + or @ref HAL_USART_Init() function. + + [..] + When The compilation define USE_HAL_USART_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available + and weak (surcharged) callbacks are used. + + @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 USART frame formats are as listed in the following table: + +-------------------------------------------------------------+ + | M bit | PCE bit | USART 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 "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup USART USART + * @brief HAL USART Synchronous module driver + * @{ + */ +#ifdef HAL_USART_MODULE_ENABLED +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup USART_Private_Constants + * @{ + */ +#define DUMMY_DATA 0xFFFFU +#define USART_TIMEOUT_VALUE 22000U +/** + * @} + */ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @addtogroup USART_Private_Functions + * @{ + */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +static void USART_EndTxTransfer(USART_HandleTypeDef *husart); +static void USART_EndRxTransfer(USART_HandleTypeDef *husart); +static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart); +static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart); +static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart); +static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart); +static void USART_SetConfig(USART_HandleTypeDef *husart); +static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma); +static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); +static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); +static void USART_DMAError(DMA_HandleTypeDef *hdma); +static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); + +static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @defgroup USART_Exported_Functions USART Exported Functions + * @{ + */ + +/** @defgroup USART_Exported_Functions_Group1 USART 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 USART + in asynchronous and in synchronous modes. + (+) 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 USART frame formats. + (++) USART polarity + (++) USART phase + (++) USART LastBit + (++) Receiver/transmitter modes + + [..] + The HAL_USART_Init() function follows the USART synchronous configuration + procedures (details for the procedures are available in reference manual + (RM0430 for STM32F4X3xx MCUs and RM0402 for STM32F412xx MCUs + RM0383 for STM32F411xC/E MCUs and RM0401 for STM32F410xx MCUs + RM0090 for STM32F4X5xx/STM32F4X7xx/STM32F429xx/STM32F439xx MCUs + RM0390 for STM32F446xx MCUs and RM0386 for STM32F469xx/STM32F479xx MCUs)). + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the USART mode according to the specified + * parameters in the USART_InitTypeDef and initialize the associated handle. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart) +{ + /* Check the USART handle allocation */ + if (husart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_USART_INSTANCE(husart->Instance)); + + if (husart->State == HAL_USART_STATE_RESET) + { + /* Allocate lock resource and initialize it */ + husart->Lock = HAL_UNLOCKED; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + USART_InitCallbacksToDefault(husart); + + if (husart->MspInitCallback == NULL) + { + husart->MspInitCallback = HAL_USART_MspInit; + } + + /* Init the low level hardware */ + husart->MspInitCallback(husart); +#else + /* Init the low level hardware : GPIO, CLOCK */ + HAL_USART_MspInit(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + + husart->State = HAL_USART_STATE_BUSY; + + /* Set the USART Communication parameters */ + USART_SetConfig(husart); + + /* In USART mode, the following bits must be kept cleared: + - LINEN bit in the USART_CR2 register + - HDSEL, SCEN and IREN bits in the USART_CR3 register */ + CLEAR_BIT(husart->Instance->CR2, USART_CR2_LINEN); + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + + /* Enable the Peripheral */ + __HAL_USART_ENABLE(husart); + + /* Initialize the USART state */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the USART peripheral. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart) +{ + /* Check the USART handle allocation */ + if (husart == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_USART_INSTANCE(husart->Instance)); + + husart->State = HAL_USART_STATE_BUSY; + + /* Disable the Peripheral */ + __HAL_USART_DISABLE(husart); + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + if (husart->MspDeInitCallback == NULL) + { + husart->MspDeInitCallback = HAL_USART_MspDeInit; + } + /* DeInit the low level hardware */ + husart->MspDeInitCallback(husart); +#else + /* DeInit the low level hardware */ + HAL_USART_MspDeInit(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_RESET; + + /* Release Lock */ + __HAL_UNLOCK(husart); + + return HAL_OK; +} + +/** + * @brief USART MSP Init. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_MspInit(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_MspInit could be implemented in the user file + */ +} + +/** + * @brief USART MSP DeInit. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User USART Callback + * To be used instead of the weak predefined callback + * @param husart usart handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @param pCallback pointer to the Callback function + * @retval HAL status ++ */ +HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID, + pUSART_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + return HAL_ERROR; + } + /* Process locked */ + __HAL_LOCK(husart); + + if (husart->State == HAL_USART_STATE_READY) + { + switch (CallbackID) + { + case HAL_USART_TX_HALFCOMPLETE_CB_ID : + husart->TxHalfCpltCallback = pCallback; + break; + + case HAL_USART_TX_COMPLETE_CB_ID : + husart->TxCpltCallback = pCallback; + break; + + case HAL_USART_RX_HALFCOMPLETE_CB_ID : + husart->RxHalfCpltCallback = pCallback; + break; + + case HAL_USART_RX_COMPLETE_CB_ID : + husart->RxCpltCallback = pCallback; + break; + + case HAL_USART_TX_RX_COMPLETE_CB_ID : + husart->TxRxCpltCallback = pCallback; + break; + + case HAL_USART_ERROR_CB_ID : + husart->ErrorCallback = pCallback; + break; + + case HAL_USART_ABORT_COMPLETE_CB_ID : + husart->AbortCpltCallback = pCallback; + break; + + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = pCallback; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (husart->State == HAL_USART_STATE_RESET) + { + switch (CallbackID) + { + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = pCallback; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(husart); + + return status; +} + +/** + * @brief Unregister an USART Callback + * USART callaback is redirected to the weak predefined callback + * @param husart usart handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID + * @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID + * @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID + * @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID + * @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + /* Process locked */ + __HAL_LOCK(husart); + + if (husart->State == HAL_USART_STATE_READY) + { + switch (CallbackID) + { + case HAL_USART_TX_HALFCOMPLETE_CB_ID : + husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + break; + + case HAL_USART_TX_COMPLETE_CB_ID : + husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + break; + + case HAL_USART_RX_HALFCOMPLETE_CB_ID : + husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + break; + + case HAL_USART_RX_COMPLETE_CB_ID : + husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + break; + + case HAL_USART_TX_RX_COMPLETE_CB_ID : + husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + break; + + case HAL_USART_ERROR_CB_ID : + husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */ + break; + + case HAL_USART_ABORT_COMPLETE_CB_ID : + husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ + break; + + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = HAL_USART_MspInit; /* Legacy weak MspInitCallback */ + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = HAL_USART_MspDeInit; /* Legacy weak MspDeInitCallback */ + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (husart->State == HAL_USART_STATE_RESET) + { + switch (CallbackID) + { + case HAL_USART_MSPINIT_CB_ID : + husart->MspInitCallback = HAL_USART_MspInit; + break; + + case HAL_USART_MSPDEINIT_CB_ID : + husart->MspDeInitCallback = HAL_USART_MspDeInit; + break; + + default : + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK; + + /* Return error status */ + status = HAL_ERROR; + } + + /* Release Lock */ + __HAL_UNLOCK(husart); + + return status; +} +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup USART_Exported_Functions_Group2 IO operation functions + * @brief USART Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the USART synchronous + data transfers. + + [..] + The USART supports master mode only: it cannot receive or send data related to an input + clock (SCLK is always an output). + + (#) 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. + (++) No-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 USART IRQ when using Interrupt mode or the DMA IRQ when + using DMA mode. + The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback() + user callbacks + will be executed respectively at the end of the transmit or Receive process + The HAL_USART_ErrorCallback() user callback will be executed when a communication + error is detected + + (#) Blocking mode APIs are : + (++) HAL_USART_Transmit() in simplex mode + (++) HAL_USART_Receive() in full duplex receive only + (++) HAL_USART_TransmitReceive() in full duplex mode + + (#) Non Blocking mode APIs with Interrupt are : + (++) HAL_USART_Transmit_IT()in simplex mode + (++) HAL_USART_Receive_IT() in full duplex receive only + (++) HAL_USART_TransmitReceive_IT() in full duplex mode + (++) HAL_USART_IRQHandler() + + (#) Non Blocking mode functions with DMA are : + (++) HAL_USART_Transmit_DMA()in simplex mode + (++) HAL_USART_Receive_DMA() in full duplex receive only + (++) HAL_USART_TransmitReceive_DMA() in full duplex mode + (++) HAL_USART_DMAPause() + (++) HAL_USART_DMAResume() + (++) HAL_USART_DMAStop() + + (#) A set of Transfer Complete Callbacks are provided in non Blocking mode: + (++) HAL_USART_TxHalfCpltCallback() + (++) HAL_USART_TxCpltCallback() + (++) HAL_USART_RxHalfCpltCallback() + (++) HAL_USART_RxCpltCallback() + (++) HAL_USART_ErrorCallback() + (++) HAL_USART_TxRxCpltCallback() + + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (++) HAL_USART_Abort() + (++) HAL_USART_Abort_IT() + + (#) For Abort services based on interrupts (HAL_USART_Abort_IT), a Abort Complete Callbacks is provided: + (++) HAL_USART_AbortCpltCallback() + + (#) 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_USART_ErrorCallback() user callback is executed. Transfer is kept ongoing on USART 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_USART_ErrorCallback() user callback is executed. + +@endverbatim + * @{ + */ + +/** + * @brief Simplex Send an amount of data in blocking mode. + * @note When USART 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 pTxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData 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_USART_Transmit(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size, uint32_t Timeout) +{ + const uint8_t *ptxdata8bits; + const uint16_t *ptxdata16bits; + uint32_t tickstart; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(husart); + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + husart->TxXferSize = Size; + husart->TxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + ptxdata8bits = NULL; + ptxdata16bits = (const uint16_t *) pTxData; + } + else + { + ptxdata8bits = pTxData; + ptxdata16bits = NULL; + } + + while (husart->TxXferCount > 0U) + { + /* Wait for TXE flag in order to write data in DR */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (ptxdata8bits == NULL) + { + husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF); + ptxdata16bits++; + } + else + { + husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF); + ptxdata8bits++; + } + + husart->TxXferCount--; + } + + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Receive an amount of data in blocking mode. + * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note When USART 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 pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pRxData 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_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout) +{ + uint8_t *prxdata8bits; + uint16_t *prxdata16bits; + uint32_t tickstart; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_RX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + husart->RxXferSize = Size; + husart->RxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + prxdata8bits = NULL; + prxdata16bits = (uint16_t *) pRxData; + } + else + { + prxdata8bits = pRxData; + prxdata16bits = NULL; + } + + /* Check the remain data to be received */ + while (husart->RxXferCount > 0U) + { + /* Wait until TXE flag is set to send dummy byte in order to generate the + * clock for the slave to send data. + * Whatever the frame length (7, 8 or 9-bit long), the same dummy value + * can be written for all the cases. */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF); + + /* Wait until RXNE flag is set to receive the byte */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (prxdata8bits == NULL) + { + *prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF); + prxdata16bits++; + } + else + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE))) + { + *prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF); + } + else + { + *prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F); + } + prxdata8bits++; + } + husart->RxXferCount--; + } + + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (blocking mode). + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData Pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData Pointer to RX data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received). + * @param Timeout Timeout duration + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size, uint32_t Timeout) +{ + uint8_t *prxdata8bits; + uint16_t *prxdata16bits; + const uint8_t *ptxdata8bits; + const uint16_t *ptxdata16bits; + uint16_t rxdatacount; + uint32_t tickstart; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + /* In case of 9bits/No Parity transfer, pTxData and pRxData buffers provided as input parameter + should be aligned on a u16 frontier, as data to be filled into TDR/retrieved from RDR will be + handled through a u16 cast. */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + if (((((uint32_t)pTxData) & 1U) != 0U) || ((((uint32_t)pRxData) & 1U) != 0U)) + { + return HAL_ERROR; + } + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_RX; + + /* Init tickstart for timeout management */ + tickstart = HAL_GetTick(); + + husart->RxXferSize = Size; + husart->TxXferSize = Size; + husart->TxXferCount = Size; + husart->RxXferCount = Size; + + /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */ + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + prxdata8bits = NULL; + ptxdata8bits = NULL; + ptxdata16bits = (const uint16_t *) pTxData; + prxdata16bits = (uint16_t *) pRxData; + } + else + { + prxdata8bits = pRxData; + ptxdata8bits = pTxData; + ptxdata16bits = NULL; + prxdata16bits = NULL; + } + + /* Check the remain data to be received */ + /* rxdatacount is a temporary variable for MISRAC2012-Rule-13.5 */ + rxdatacount = husart->RxXferCount; + while ((husart->TxXferCount > 0U) || (rxdatacount > 0U)) + { + if (husart->TxXferCount > 0U) + { + /* Wait for TXE flag in order to write data in DR */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + + if (ptxdata8bits == NULL) + { + husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF); + ptxdata16bits++; + } + else + { + husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF); + ptxdata8bits++; + } + + husart->TxXferCount--; + } + + if (husart->RxXferCount > 0U) + { + /* Wait for RXNE Flag */ + if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } + if (prxdata8bits == NULL) + { + *prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF); + prxdata16bits++; + } + else + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE))) + { + *prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF); + } + else + { + *prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F); + } + + prxdata8bits++; + } + + husart->RxXferCount--; + } + rxdatacount = husart->RxXferCount; + } + + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Simplex Send an amount of data in non-blocking mode. + * @note When USART 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 pTxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent. + * @retval HAL status + * @note The USART errors are not managed to avoid the overrun error. + */ +HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size) +{ + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pTxBuffPtr = pTxData; + husart->TxXferSize = Size; + husart->TxXferCount = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX; + + /* The USART Error Interrupts: (Frame error, Noise error, Overrun error) + are not managed by the USART transmit process to avoid the overrun interrupt + when the USART mode is configured for transmit and receive "USART_MODE_TX_RX" + to benefit for the frame error and noise interrupts the USART mode should be + configured only for transmit "USART_MODE_TX" + The __HAL_USART_ENABLE_IT(husart, USART_IT_ERR) can be used to enable the Frame error, + Noise error interrupt */ + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Transmit Data Register Empty Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Simplex Receive an amount of data in non-blocking mode. + * @note To receive synchronous data, dummy data are simultaneously transmitted. + * @note When USART 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 pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pRxData 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_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size) +{ + if (husart->State == HAL_USART_STATE_READY) + { + if ((pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pRxBuffPtr = pRxData; + husart->RxXferSize = Size; + husart->RxXferCount = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_RX; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + if (husart->Init.Parity != USART_PARITY_NONE) + { + /* Enable the USART Parity Error and Data Register not empty Interrupts */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); + } + else + { + /* Enable the USART Data Register not empty Interrupts */ + SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE); + } + + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Send dummy byte in order to generate the clock for the slave to send data */ + husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x01FF); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (non-blocking). + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData Pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData Pointer to RX data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received). + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) +{ + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pRxBuffPtr = pRxData; + husart->RxXferSize = Size; + husart->RxXferCount = Size; + husart->pTxBuffPtr = pTxData; + husart->TxXferSize = Size; + husart->TxXferCount = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX_RX; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the USART Data Register not empty Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE); + + if (husart->Init.Parity != USART_PARITY_NONE) + { + /* Enable the USART Parity Error Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + } + + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Enable the USART Transmit Data Register Empty Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Simplex Send an amount of data in DMA mode. + * @note When USART 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 pTxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData 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_USART_Transmit_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size) +{ + const uint32_t *tmp; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pTxBuffPtr = pTxData; + husart->TxXferSize = Size; + husart->TxXferCount = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX; + + /* Set the USART DMA transfer complete callback */ + husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; + + /* Set the USART DMA Half transfer complete callback */ + husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; + + /* Set the DMA error callback */ + husart->hdmatx->XferErrorCallback = USART_DMAError; + + /* Set the DMA abort callback */ + husart->hdmatx->XferAbortCallback = NULL; + + /* Enable the USART transmit DMA stream */ + tmp = (const uint32_t *)&pTxData; + HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC); + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Receive an amount of data in DMA mode. + * @note When USART 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 pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pRxData Pointer to data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received. + * @retval HAL status + * @note The USART DMA transmit stream must be configured in order to generate the clock for the slave. + * @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit. + */ +HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size) +{ + uint32_t *tmp; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pRxBuffPtr = pRxData; + husart->RxXferSize = Size; + husart->pTxBuffPtr = pRxData; + husart->TxXferSize = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_RX; + + /* Set the USART DMA Rx transfer complete callback */ + husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; + + /* Set the USART DMA Half transfer complete callback */ + husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; + + /* Set the USART DMA Rx transfer error callback */ + husart->hdmarx->XferErrorCallback = USART_DMAError; + + /* Set the DMA abort callback */ + husart->hdmarx->XferAbortCallback = NULL; + + /* Set the USART Tx DMA transfer complete callback as NULL because the communication closing + is performed in DMA reception complete callback */ + husart->hdmatx->XferHalfCpltCallback = NULL; + husart->hdmatx->XferCpltCallback = NULL; + + /* Set the DMA error callback */ + husart->hdmatx->XferErrorCallback = USART_DMAError; + + /* Set the DMA AbortCpltCallback */ + husart->hdmatx->XferAbortCallback = NULL; + + /* Enable the USART receive DMA stream */ + tmp = (uint32_t *)&pRxData; + HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(uint32_t *)tmp, Size); + + /* Enable the USART transmit DMA stream: the transmit stream is used in order + to generate in the non-blocking mode the clock to the slave device, + this mode isn't a simplex receive mode but a full-duplex receive one */ + HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size); + + /* Clear the Overrun flag just before enabling the DMA Rx request: mandatory for the second transfer */ + __HAL_USART_CLEAR_OREFLAG(husart); + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + if (husart->Init.Parity != USART_PARITY_NONE) + { + /* Enable the USART Parity Error Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + } + + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Transmit Receive an amount of data in DMA mode. + * @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number + * of u16 available through pTxData and through pRxData. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param pTxData Pointer to TX data buffer (u8 or u16 data elements). + * @param pRxData Pointer to RX data buffer (u8 or u16 data elements). + * @param Size Amount of data elements (u8 or u16) to be received/sent. + * @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData, + uint16_t Size) +{ + const uint32_t *tmp; + + if (husart->State == HAL_USART_STATE_READY) + { + if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0)) + { + return HAL_ERROR; + } + /* Process Locked */ + __HAL_LOCK(husart); + + husart->pRxBuffPtr = pRxData; + husart->RxXferSize = Size; + husart->pTxBuffPtr = pTxData; + husart->TxXferSize = Size; + + husart->ErrorCode = HAL_USART_ERROR_NONE; + husart->State = HAL_USART_STATE_BUSY_TX_RX; + + /* Set the USART DMA Rx transfer complete callback */ + husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt; + + /* Set the USART DMA Half transfer complete callback */ + husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt; + + /* Set the USART DMA Tx transfer complete callback */ + husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt; + + /* Set the USART DMA Half transfer complete callback */ + husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt; + + /* Set the USART DMA Tx transfer error callback */ + husart->hdmatx->XferErrorCallback = USART_DMAError; + + /* Set the USART DMA Rx transfer error callback */ + husart->hdmarx->XferErrorCallback = USART_DMAError; + + /* Set the DMA abort callback */ + husart->hdmarx->XferAbortCallback = NULL; + + /* Enable the USART receive DMA stream */ + tmp = (uint32_t *)&pRxData; + HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(const uint32_t *)tmp, Size); + + /* Enable the USART transmit DMA stream */ + tmp = (const uint32_t *)&pTxData; + HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size); + + /* Clear the TC flag in the SR register by writing 0 to it */ + __HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC); + + /* Clear the Overrun flag: mandatory for the second transfer in circular mode */ + __HAL_USART_CLEAR_OREFLAG(husart); + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + if (husart->Init.Parity != USART_PARITY_NONE) + { + /* Enable the USART Parity Error Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_PEIE); + } + + /* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAR); + + /* Enable the DMA transfer for transmit request by setting the DMAT bit + in the USART CR3 register */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Pauses the DMA Transfer. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart) +{ + /* Process Locked */ + __HAL_LOCK(husart); + + /* Disable the USART DMA Tx request */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; +} + +/** + * @brief Resumes the DMA Transfer. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart) +{ + /* Process Locked */ + __HAL_LOCK(husart); + + /* Enable the USART DMA Tx request */ + SET_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_OK; +} + +/** + * @brief Stops the DMA Transfer. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart) +{ + uint32_t dmarequest = 0x00U; + /* The Lock is not implemented on this API to allow the user application + to call the HAL USART API under callbacks HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback(): + when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated + and the correspond call back is executed HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback() + */ + + /* Stop USART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT); + if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest) + { + USART_EndTxTransfer(husart); + + /* Abort the USART DMA Tx channel */ + if (husart->hdmatx != NULL) + { + HAL_DMA_Abort(husart->hdmatx); + } + + /* Disable the USART Tx DMA request */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + } + + /* Stop USART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR); + if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest) + { + USART_EndRxTransfer(husart); + + /* Abort the USART DMA Rx channel */ + if (husart->hdmarx != NULL) + { + HAL_DMA_Abort(husart->hdmarx); + } + + /* Disable the USART Rx DMA request */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfer (blocking mode). + * @param husart USART handle. + * @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx, + * as described by TransferType parameter) started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts (depending of transfer direction) + * - 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_USART_Abort(USART_HandleTypeDef *husart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Disable the USART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the USART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if (husart->hdmatx != NULL) + { + /* Set the USART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + husart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(husart->hdmatx); + } + } + + /* Disable the USART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the USART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if (husart->hdmarx != NULL) + { + /* Set the USART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + husart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(husart->hdmarx); + } + } + + /* Reset Tx and Rx transfer counters */ + husart->TxXferCount = 0x00U; + husart->RxXferCount = 0x00U; + + /* Restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* Reset Handle ErrorCode to No Error */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfer (Interrupt mode). + * @param husart USART handle. + * @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx, + * as described by TransferType parameter) started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable PPP Interrupts (depending of transfer direction) + * - 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_USART_Abort_IT(USART_HandleTypeDef *husart) +{ + uint32_t AbortCplt = 0x01U; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to USART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if (husart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if USART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) + { + husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback; + } + else + { + husart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if (husart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if USART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) + { + husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback; + } + else + { + husart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the USART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at USART level */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the USART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if (husart->hdmatx != NULL) + { + /* USART Tx DMA Abort callback has already been initialised : + will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK) + { + husart->hdmatx->XferAbortCallback = NULL; + } + else + { + AbortCplt = 0x00U; + } + } + } + + /* Disable the USART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the USART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if (husart->hdmarx != NULL) + { + /* USART Rx DMA Abort callback has already been initialised : + will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) + { + husart->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 */ + husart->TxXferCount = 0x00U; + husart->RxXferCount = 0x00U; + + /* Reset errorCode */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + + /* Restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ + HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + + return HAL_OK; +} + +/** + * @brief This function handles USART interrupt request. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +void HAL_USART_IRQHandler(USART_HandleTypeDef *husart) +{ + uint32_t isrflags = READ_REG(husart->Instance->SR); + uint32_t cr1its = READ_REG(husart->Instance->CR1); + uint32_t cr3its = READ_REG(husart->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) + { + /* USART in mode Receiver -------------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + if (husart->State == HAL_USART_STATE_BUSY_RX) + { + USART_Receive_IT(husart); + } + else + { + USART_TransmitReceive_IT(husart); + } + return; + } + } + /* If some errors occur */ + if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET))) + { + /* USART parity error interrupt occurred ----------------------------------*/ + if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + husart->ErrorCode |= HAL_USART_ERROR_PE; + } + + /* USART noise error interrupt occurred --------------------------------*/ + if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + husart->ErrorCode |= HAL_USART_ERROR_NE; + } + + /* USART frame error interrupt occurred --------------------------------*/ + if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + husart->ErrorCode |= HAL_USART_ERROR_FE; + } + + /* USART Over-Run interrupt occurred -----------------------------------*/ + if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET))) + { + husart->ErrorCode |= HAL_USART_ERROR_ORE; + } + + if (husart->ErrorCode != HAL_USART_ERROR_NONE) + { + /* USART in mode Receiver -----------------------------------------------*/ + if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + if (husart->State == HAL_USART_STATE_BUSY_RX) + { + USART_Receive_IT(husart); + } + else + { + USART_TransmitReceive_IT(husart); + } + } + /* If Overrun error occurs, or if any error occurs in DMA mode reception, + consider error as blocking */ + dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR); + if (((husart->ErrorCode & HAL_USART_ERROR_ORE) != RESET) || dmarequest) + { + /* Set the USART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + USART_EndRxTransfer(husart); + + /* Disable the USART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the USART DMA Rx channel */ + if (husart->hdmarx != NULL) + { + /* Set the USART DMA Abort callback : + will lead to call HAL_USART_ErrorCallback() at end of DMA abort procedure */ + husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError; + + if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK) + { + /* Call Directly XferAbortCallback function in case of error */ + husart->hdmarx->XferAbortCallback(husart->hdmarx); + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ + HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ + HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + } + else + { + /* Call user error callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ + HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + } + } + return; + } + + /* USART in mode Transmitter -----------------------------------------------*/ + if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) + { + if (husart->State == HAL_USART_STATE_BUSY_TX) + { + USART_Transmit_IT(husart); + } + else + { + USART_TransmitReceive_IT(husart); + } + return; + } + + /* USART in mode Transmitter (transmission end) ----------------------------*/ + if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) + { + USART_EndTransmit_IT(husart); + return; + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx Half Transfer completed callbacks. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_TxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Half Transfer completed callbacks. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_RxHalfCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Tx/Rx Transfers completed callback for the non-blocking process. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_TxRxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief USART error callbacks. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +__weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_USART_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief USART Abort Complete callback. + * @param husart USART handle. + * @retval None + */ +__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(husart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_USART_AbortCpltCallback can be implemented in the user file. + */ +} + +/** + * @} + */ + +/** @defgroup USART_Exported_Functions_Group3 Peripheral State and Errors functions + * @brief USART State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + USART communication + process, return Peripheral Errors occurred during communication process + (+) HAL_USART_GetState() API can be helpful to check in run-time the state + of the USART peripheral. + (+) HAL_USART_GetError() check in run-time errors that could be occurred during + communication. +@endverbatim + * @{ + */ + +/** + * @brief Returns the USART state. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL state + */ +HAL_USART_StateTypeDef HAL_USART_GetState(const USART_HandleTypeDef *husart) +{ + return husart->State; +} + +/** + * @brief Return the USART error code + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART. + * @retval USART Error Code + */ +uint32_t HAL_USART_GetError(const USART_HandleTypeDef *husart) +{ + return husart->ErrorCode; +} + +/** + * @} + */ + +/** @defgroup USART_Private_Functions USART Private Functions + * @{ + */ + +/** + * @brief Initialize the callbacks to their default values. + * @param husart USART handle. + * @retval none + */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) +void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart) +{ + /* Init the USART Callback settings */ + husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */ + husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */ + husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */ + husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */ + husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */ + husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */ + husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */ +} +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + +/** + * @brief DMA USART 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 USART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* DMA Normal mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + husart->TxXferCount = 0U; + if (husart->State == HAL_USART_STATE_BUSY_TX) + { + /* Disable the DMA transfer for transmit request by resetting the DMAT bit + in the USART CR3 register */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the USART Transmit Complete Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_TCIE); + } + } + /* DMA Circular mode */ + else + { + if (husart->State == HAL_USART_STATE_BUSY_TX) + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Complete Callback */ + husart->TxCpltCallback(husart); +#else + /* Call legacy weak Tx Complete Callback */ + HAL_USART_TxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief DMA USART 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 USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Half Complete Callback */ + husart->TxHalfCpltCallback(husart); +#else + /* Call legacy weak Tx Half Complete Callback */ + HAL_USART_TxHalfCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA USART 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 USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + /* DMA Normal mode */ + if ((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U) + { + husart->RxXferCount = 0x00U; + + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the Transmit/receiver request by clearing the DMAT/DMAR bit + in the USART CR3 register */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR); + CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT); + + /* The USART state is HAL_USART_STATE_BUSY_RX */ + if (husart->State == HAL_USART_STATE_BUSY_RX) + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + /* The USART state is HAL_USART_STATE_BUSY_TX_RX */ + else + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + husart->State = HAL_USART_STATE_READY; + } + /* DMA circular mode */ + else + { + if (husart->State == HAL_USART_STATE_BUSY_RX) + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + /* The USART state is HAL_USART_STATE_BUSY_TX_RX */ + else + { +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + } + } +} + +/** + * @brief DMA USART 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 USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Half Complete Callback */ + husart->RxHalfCpltCallback(husart); +#else + /* Call legacy weak Rx Half Complete Callback */ + HAL_USART_RxHalfCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA USART 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 USART_DMAError(DMA_HandleTypeDef *hdma) +{ + uint32_t dmarequest = 0x00U; + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + husart->RxXferCount = 0x00U; + husart->TxXferCount = 0x00U; + + /* Stop USART DMA Tx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT); + if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest) + { + USART_EndTxTransfer(husart); + } + + /* Stop USART DMA Rx request if ongoing */ + dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR); + if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest) + { + USART_EndRxTransfer(husart); + } + + husart->ErrorCode |= HAL_USART_ERROR_DMA; + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ + HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief This function handles USART Communication Timeout. It waits + * until a flag is no longer in the specified status. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @param Flag specifies the USART 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 USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status, + uint32_t Tickstart, uint32_t Timeout) +{ + /* Wait until flag is set */ + while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout)) + { + /* Disable the USART Transmit Complete Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + + /* Disable the USART RXNE Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE); + + /* Disable the USART Parity Error Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + husart->State = HAL_USART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(husart); + + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief End ongoing Tx transfer on USART peripheral (following error detection or Transmit completion). + * @param husart USART handle. + * @retval None + */ +static void USART_EndTxTransfer(USART_HandleTypeDef *husart) +{ + /* Disable TXEIE and TCIE interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE)); + + /* At end of Tx process, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; +} + +/** + * @brief End ongoing Rx transfer on USART peripheral (following error detection or Reception completion). + * @param husart USART handle. + * @retval None + */ +static void USART_EndRxTransfer(USART_HandleTypeDef *husart) +{ + /* Disable RXNE, PE and ERR interrupts */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; +} + +/** + * @brief DMA USART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + husart->RxXferCount = 0x00U; + husart->TxXferCount = 0x00U; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Error Callback */ + husart->ErrorCallback(husart); +#else + /* Call legacy weak Error Callback */ + HAL_USART_ErrorCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA USART 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 DMA handle. + * @retval None + */ +static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + husart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (husart->hdmarx != NULL) + { + if (husart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + husart->TxXferCount = 0x00U; + husart->RxXferCount = 0x00U; + + /* Reset errorCode */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + + /* Restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ + HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief DMA USART 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 DMA handle. + * @retval None + */ +static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; + + husart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if (husart->hdmatx != NULL) + { + if (husart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + husart->TxXferCount = 0x00U; + husart->RxXferCount = 0x00U; + + /* Reset errorCode */ + husart->ErrorCode = HAL_USART_ERROR_NONE; + + /* Restore husart->State to Ready */ + husart->State = HAL_USART_STATE_READY; + + /* Call user Abort complete callback */ +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Abort Complete Callback */ + husart->AbortCpltCallback(husart); +#else + /* Call legacy weak Abort Complete Callback */ + HAL_USART_AbortCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ +} + +/** + * @brief Simplex Send an amount of data in non-blocking mode. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + * @note The USART errors are not managed to avoid the overrun error. + */ +static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart) +{ + const uint16_t *tmp; + + if (husart->State == HAL_USART_STATE_BUSY_TX) + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + tmp = (const uint16_t *) husart->pTxBuffPtr; + husart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF); + husart->pTxBuffPtr += 2U; + } + else + { + husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF); + } + + if (--husart->TxXferCount == 0U) + { + /* Disable the USART Transmit data register empty Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + + /* Enable the USART Transmit Complete Interrupt */ + SET_BIT(husart->Instance->CR1, USART_CR1_TCIE); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Wraps up transmission in non blocking mode. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart) +{ + /* Disable the USART Transmit Complete Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_TCIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Complete Callback */ + husart->TxCpltCallback(husart); +#else + /* Call legacy weak Tx Complete Callback */ + HAL_USART_TxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + + return HAL_OK; +} + +/** + * @brief Simplex Receive an amount of data in non-blocking mode. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart) +{ + uint8_t *pdata8bits; + uint16_t *pdata16bits; + + if (husart->State == HAL_USART_STATE_BUSY_RX) + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + pdata8bits = NULL; + pdata16bits = (uint16_t *) husart->pRxBuffPtr; + *pdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF); + husart->pRxBuffPtr += 2U; + } + else + { + pdata8bits = (uint8_t *) husart->pRxBuffPtr; + pdata16bits = NULL; + + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE))) + { + *pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F); + } + + husart->pRxBuffPtr += 1U; + } + + husart->RxXferCount--; + + if (husart->RxXferCount == 0U) + { + /* Disable the USART RXNE Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE); + + /* Disable the USART Parity Error Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + husart->State = HAL_USART_STATE_READY; +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Rx Complete Callback */ + husart->RxCpltCallback(husart); +#else + /* Call legacy weak Rx Complete Callback */ + HAL_USART_RxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + + return HAL_OK; + } + else + { + /* Send dummy byte in order to generate the clock for the slave to send the next data. + * Whatever the frame length (7, 8 or 9-bit long), the same dummy value + * can be written for all the cases. */ + husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF); + } + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Full-Duplex Send receive an amount of data in full-duplex mode (non-blocking). + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval HAL status + */ +static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart) +{ + const uint16_t *pdatatx16bits; + uint16_t *pdatarx16bits; + + if (husart->State == HAL_USART_STATE_BUSY_TX_RX) + { + if (husart->TxXferCount != 0x00U) + { + if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE) != RESET) + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + pdatatx16bits = (const uint16_t *) husart->pTxBuffPtr; + husart->Instance->DR = (uint16_t)(*pdatatx16bits & (uint16_t)0x01FF); + husart->pTxBuffPtr += 2U; + } + else + { + husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF); + } + + husart->TxXferCount--; + + /* Check the latest data transmitted */ + if (husart->TxXferCount == 0U) + { + CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE); + } + } + } + + if (husart->RxXferCount != 0x00U) + { + if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXNE) != RESET) + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE)) + { + pdatarx16bits = (uint16_t *) husart->pRxBuffPtr; + *pdatarx16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF); + husart->pRxBuffPtr += 2U; + } + else + { + if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE))) + { + *husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF); + } + else + { + *husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F); + } + husart->pRxBuffPtr += 1U; + } + + husart->RxXferCount--; + } + } + + /* Check the latest data received */ + if (husart->RxXferCount == 0U) + { + /* Disable the USART RXNE Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE); + + /* Disable the USART Parity Error Interrupt */ + CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE); + + /* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE); + + husart->State = HAL_USART_STATE_READY; + +#if (USE_HAL_USART_REGISTER_CALLBACKS == 1) + /* Call registered Tx Rx Complete Callback */ + husart->TxRxCpltCallback(husart); +#else + /* Call legacy weak Tx Rx Complete Callback */ + HAL_USART_TxRxCpltCallback(husart); +#endif /* USE_HAL_USART_REGISTER_CALLBACKS */ + + return HAL_OK; + } + + return HAL_OK; + } + else + { + return HAL_BUSY; + } +} + +/** + * @brief Configures the USART peripheral. + * @param husart Pointer to a USART_HandleTypeDef structure that contains + * the configuration information for the specified USART module. + * @retval None + */ +static void USART_SetConfig(USART_HandleTypeDef *husart) +{ + uint32_t tmpreg = 0x00U; + uint32_t pclk; + + /* Check the parameters */ + assert_param(IS_USART_INSTANCE(husart->Instance)); + assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity)); + assert_param(IS_USART_PHASE(husart->Init.CLKPhase)); + assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit)); + assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate)); + assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength)); + assert_param(IS_USART_STOPBITS(husart->Init.StopBits)); + assert_param(IS_USART_PARITY(husart->Init.Parity)); + assert_param(IS_USART_MODE(husart->Init.Mode)); + + /* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the + receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */ + CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE)); + + /*---------------------------- USART CR2 Configuration ---------------------*/ + tmpreg = husart->Instance->CR2; + /* Clear CLKEN, CPOL, CPHA and LBCL bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP)); + /* Configure the USART Clock, CPOL, CPHA and LastBit -----------------------*/ + /* Set CPOL bit according to husart->Init.CLKPolarity value */ + /* Set CPHA bit according to husart->Init.CLKPhase value */ + /* Set LBCL bit according to husart->Init.CLKLastBit value */ + /* Set Stop Bits: Set STOP[13:12] bits according to husart->Init.StopBits value */ + tmpreg |= (uint32_t)(USART_CLOCK_ENABLE | husart->Init.CLKPolarity | + husart->Init.CLKPhase | husart->Init.CLKLastBit | husart->Init.StopBits); + /* Write to USART CR2 */ + WRITE_REG(husart->Instance->CR2, (uint32_t)tmpreg); + + /*-------------------------- USART CR1 Configuration -----------------------*/ + tmpreg = husart->Instance->CR1; + + /* Clear M, PCE, PS, TE, RE and OVER8 bits */ + tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ + USART_CR1_RE | USART_CR1_OVER8)); + + /* Configure the USART Word Length, Parity and mode: + Set the M bits according to husart->Init.WordLength value + Set PCE and PS bits according to husart->Init.Parity value + Set TE and RE bits according to husart->Init.Mode value + Force OVER8 bit to 1 in order to reach the max USART frequencies */ + tmpreg |= (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode | USART_CR1_OVER8; + + /* Write to USART CR1 */ + WRITE_REG(husart->Instance->CR1, (uint32_t)tmpreg); + + /*-------------------------- USART CR3 Configuration -----------------------*/ + /* Clear CTSE and RTSE bits */ + CLEAR_BIT(husart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE)); + + /*-------------------------- USART BRR Configuration -----------------------*/ +#if defined(USART6) && defined(UART9) && defined(UART10) + if ((husart->Instance == USART1) || (husart->Instance == USART6) || (husart->Instance == UART9) || (husart->Instance == UART10)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate); + } +#elif defined(USART6) + if((husart->Instance == USART1) || (husart->Instance == USART6)) + { + pclk = HAL_RCC_GetPCLK2Freq(); + husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate); + } +#else + if(husart->Instance == USART1) + { + pclk = HAL_RCC_GetPCLK2Freq(); + husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate); + } +#endif /* USART6 || UART9 || UART10 */ + else + { + pclk = HAL_RCC_GetPCLK1Freq(); + husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate); + } +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_USART_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c new file mode 100644 index 0000000..216ea2b --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_wwdg.c @@ -0,0 +1,420 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_wwdg.c + * @author MCD Application Team + * @brief WWDG HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Window Watchdog (WWDG) peripheral: + * + Initialization and Configuration functions + * + IO operation 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 + ============================================================================== + ##### WWDG Specific features ##### + ============================================================================== + [..] + Once enabled the WWDG generates a system reset on expiry of a programmed + time period, unless the program refreshes the counter (T[6;0] downcounter) + before reaching 0x3F value (i.e. a reset is generated when the counter + value rolls down from 0x40 to 0x3F). + + (+) An MCU reset is also generated if the counter value is refreshed + before the counter has reached the refresh window value. This + implies that the counter must be refreshed in a limited window. + (+) Once enabled the WWDG cannot be disabled except by a system reset. + (+) If required by application, an Early Wakeup Interrupt can be triggered + in order to be warned before WWDG expiration. The Early Wakeup Interrupt + (EWI) can be used if specific safety operations or data logging must + be performed before the actual reset is generated. When the downcounter + reaches 0x40, interrupt occurs. This mechanism requires WWDG interrupt + line to be enabled in NVIC. Once enabled, EWI interrupt cannot be + disabled except by a system reset. + (+) WWDGRST flag in RCC CSR register can be used to inform when a WWDG + reset occurs. + (+) The WWDG counter input clock is derived from the APB clock divided + by a programmable prescaler. + (+) WWDG clock (Hz) = PCLK1 / (4096 * Prescaler) + (+) WWDG timeout (mS) = 1000 * (T[5;0] + 1) / WWDG clock (Hz) + where T[5;0] are the lowest 6 bits of Counter. + (+) WWDG Counter refresh is allowed between the following limits : + (++) min time (mS) = 1000 * (Counter - Window) / WWDG clock + (++) max time (mS) = 1000 * (Counter - 0x40) / WWDG clock + (+) Typical values: + (++) Counter min (T[5;0] = 0x00) at 42MHz (PCLK1) with zero prescaler: + max timeout before reset: approximately 97.52us + (++) Counter max (T[5;0] = 0x3F) at 42MHz (PCLK1) with prescaler + dividing by 8: + max timeout before reset: approximately 49.93ms + + ##### How to use this driver ##### + ============================================================================== + + *** Common driver usage *** + =========================== + + [..] + (+) Enable WWDG APB1 clock using __HAL_RCC_WWDG_CLK_ENABLE(). + (+) Configure the WWDG prescaler, refresh window value, counter value and early + interrupt status using HAL_WWDG_Init() function. This will automatically + enable WWDG and start its downcounter. Time reference can be taken from + function exit. Care must be taken to provide a counter value + greater than 0x40 to prevent generation of immediate reset. + (+) If the Early Wakeup Interrupt (EWI) feature is enabled, an interrupt is + generated when the counter reaches 0x40. When HAL_WWDG_IRQHandler is + triggered by the interrupt service routine, flag will be automatically + cleared and HAL_WWDG_WakeupCallback user callback will be executed. User + can add his own code by customization of callback HAL_WWDG_WakeupCallback. + (+) Then the application program must refresh the WWDG counter at regular + intervals during normal operation to prevent an MCU reset, using + HAL_WWDG_Refresh() function. This operation must occur only when + the counter is lower than the refresh window value already programmed. + + *** Callback registration *** + ============================= + + [..] + The compilation define USE_HAL_WWDG_REGISTER_CALLBACKS when set to 1 allows + the user to configure dynamically the driver callbacks. Use Functions + HAL_WWDG_RegisterCallback() to register a user callback. + + (+) Function HAL_WWDG_RegisterCallback() allows to register following + callbacks: + (++) EwiCallback : callback for Early WakeUp Interrupt. + (++) MspInitCallback : WWDG MspInit. + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + (+) Use function HAL_WWDG_UnRegisterCallback() to reset a callback to + the default weak (surcharged) function. HAL_WWDG_UnRegisterCallback() + takes as parameters the HAL peripheral handle and the Callback ID. + This function allows to reset following callbacks: + (++) EwiCallback : callback for Early WakeUp Interrupt. + (++) MspInitCallback : WWDG MspInit. + + [..] + When calling HAL_WWDG_Init function, callbacks are reset to the + corresponding legacy weak (surcharged) functions: + HAL_WWDG_EarlyWakeupCallback() and HAL_WWDG_MspInit() only if they have + not been registered before. + + [..] + When compilation define USE_HAL_WWDG_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registering feature is not available + and weak (surcharged) callbacks are used. + + *** WWDG HAL driver macros list *** + =================================== + [..] + Below the list of available macros in WWDG HAL driver. + (+) __HAL_WWDG_ENABLE: Enable the WWDG peripheral + (+) __HAL_WWDG_GET_FLAG: Get the selected WWDG's flag status + (+) __HAL_WWDG_CLEAR_FLAG: Clear the WWDG's pending flags + (+) __HAL_WWDG_ENABLE_IT: Enable the WWDG early wakeup interrupt + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +#ifdef HAL_WWDG_MODULE_ENABLED +/** @defgroup WWDG WWDG + * @brief WWDG HAL module driver. + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup WWDG_Exported_Functions WWDG Exported Functions + * @{ + */ + +/** @defgroup WWDG_Exported_Functions_Group1 Initialization and Configuration functions + * @brief Initialization and Configuration functions. + * +@verbatim + ============================================================================== + ##### Initialization and Configuration functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and start the WWDG according to the specified parameters + in the WWDG_InitTypeDef of associated handle. + (+) Initialize the WWDG MSP. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the WWDG according to the specified. + * parameters in the WWDG_InitTypeDef of associated handle. + * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains + * the configuration information for the specified WWDG module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg) +{ + /* Check the WWDG handle allocation */ + if (hwwdg == NULL) + { + return HAL_ERROR; + } + + /* Check the parameters */ + assert_param(IS_WWDG_ALL_INSTANCE(hwwdg->Instance)); + assert_param(IS_WWDG_PRESCALER(hwwdg->Init.Prescaler)); + assert_param(IS_WWDG_WINDOW(hwwdg->Init.Window)); + assert_param(IS_WWDG_COUNTER(hwwdg->Init.Counter)); + assert_param(IS_WWDG_EWI_MODE(hwwdg->Init.EWIMode)); + +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) + /* Reset Callback pointers */ + if (hwwdg->EwiCallback == NULL) + { + hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback; + } + + if (hwwdg->MspInitCallback == NULL) + { + hwwdg->MspInitCallback = HAL_WWDG_MspInit; + } + + /* Init the low level hardware */ + hwwdg->MspInitCallback(hwwdg); +#else + /* Init the low level hardware */ + HAL_WWDG_MspInit(hwwdg); +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ + + /* Set WWDG Counter */ + WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter)); + + /* Set WWDG Prescaler and Window */ + WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window)); + + /* Return function status */ + return HAL_OK; +} + + +/** + * @brief Initialize the WWDG MSP. + * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains + * the configuration information for the specified WWDG module. + * @note When rewriting this function in user file, mechanism may be added + * to avoid multiple initialize when HAL_WWDG_Init function is called + * again to change parameters. + * @retval None + */ +__weak void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hwwdg); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_WWDG_MspInit could be implemented in the user file + */ +} + + +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User WWDG Callback + * To be used instead of the weak (surcharged) predefined callback + * @param hwwdg WWDG handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID + * @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_WWDG_RegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID, + pWWDG_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + status = HAL_ERROR; + } + else + { + switch (CallbackID) + { + case HAL_WWDG_EWI_CB_ID: + hwwdg->EwiCallback = pCallback; + break; + + case HAL_WWDG_MSPINIT_CB_ID: + hwwdg->MspInitCallback = pCallback; + break; + + default: + status = HAL_ERROR; + break; + } + } + + return status; +} + + +/** + * @brief Unregister a WWDG Callback + * WWDG Callback is redirected to the weak (surcharged) predefined callback + * @param hwwdg WWDG handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID + * @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_WWDG_UnRegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + switch (CallbackID) + { + case HAL_WWDG_EWI_CB_ID: + hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback; + break; + + case HAL_WWDG_MSPINIT_CB_ID: + hwwdg->MspInitCallback = HAL_WWDG_MspInit; + break; + + default: + status = HAL_ERROR; + break; + } + + return status; +} +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup WWDG_Exported_Functions_Group2 IO operation functions + * @brief IO operation functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Refresh the WWDG. + (+) Handle WWDG interrupt request and associated function callback. + +@endverbatim + * @{ + */ + +/** + * @brief Refresh the WWDG. + * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains + * the configuration information for the specified WWDG module. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg) +{ + /* Write to WWDG CR the WWDG Counter value to refresh with */ + WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter)); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Handle WWDG interrupt request. + * @note The Early Wakeup Interrupt (EWI) can be used if specific safety operations + * or data logging must be performed before the actual reset is generated. + * The EWI interrupt is enabled by calling HAL_WWDG_Init function with + * EWIMode set to WWDG_EWI_ENABLE. + * When the downcounter reaches the value 0x40, and EWI interrupt is + * generated and the corresponding Interrupt Service Routine (ISR) can + * be used to trigger specific actions (such as communications or data + * logging), before resetting the device. + * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains + * the configuration information for the specified WWDG module. + * @retval None + */ +void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg) +{ + /* Check if Early Wakeup Interrupt is enable */ + if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET) + { + /* Check if WWDG Early Wakeup Interrupt occurred */ + if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET) + { + /* Clear the WWDG Early Wakeup flag */ + __HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF); + +#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1) + /* Early Wakeup registered callback */ + hwwdg->EwiCallback(hwwdg); +#else + /* Early Wakeup callback */ + HAL_WWDG_EarlyWakeupCallback(hwwdg); +#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */ + } + } +} + + +/** + * @brief WWDG Early Wakeup callback. + * @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains + * the configuration information for the specified WWDG module. + * @retval None + */ +__weak void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(hwwdg); + + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_WWDG_EarlyWakeupCallback could be implemented in the user file + */ +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_WWDG_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c new file mode 100644 index 0000000..cdb750f --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_adc.c @@ -0,0 +1,922 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_adc.c + * @author MCD Application Team + * @brief ADC LL module driver + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_adc.h" +#include "stm32f4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (ADC1) || defined (ADC2) || defined (ADC3) + +/** @addtogroup ADC_LL ADC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/** @addtogroup ADC_LL_Private_Macros + * @{ + */ + +/* Check of parameters for configuration of ADC hierarchical scope: */ +/* common to several ADC instances. */ +#define IS_LL_ADC_COMMON_CLOCK(__CLOCK__) \ + ( ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV2) \ + || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV4) \ + || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV6) \ + || ((__CLOCK__) == LL_ADC_CLOCK_SYNC_PCLK_DIV8) \ + ) + +/* Check of parameters for configuration of ADC hierarchical scope: */ +/* ADC instance. */ +#define IS_LL_ADC_RESOLUTION(__RESOLUTION__) \ + ( ((__RESOLUTION__) == LL_ADC_RESOLUTION_12B) \ + || ((__RESOLUTION__) == LL_ADC_RESOLUTION_10B) \ + || ((__RESOLUTION__) == LL_ADC_RESOLUTION_8B) \ + || ((__RESOLUTION__) == LL_ADC_RESOLUTION_6B) \ + ) + +#define IS_LL_ADC_DATA_ALIGN(__DATA_ALIGN__) \ + ( ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_RIGHT) \ + || ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_LEFT) \ + ) + +#define IS_LL_ADC_SCAN_SELECTION(__SCAN_SELECTION__) \ + ( ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_DISABLE) \ + || ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_ENABLE) \ + ) + +#define IS_LL_ADC_SEQ_SCAN_MODE(__SEQ_SCAN_MODE__) \ + ( ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_DISABLE) \ + || ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_ENABLE) \ + ) + +/* Check of parameters for configuration of ADC hierarchical scope: */ +/* ADC group regular */ +#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \ + ( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH3) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH4) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_CH1) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH1) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH2) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH3) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_CH1) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \ + || ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \ + ) +#define IS_LL_ADC_REG_CONTINUOUS_MODE(__REG_CONTINUOUS_MODE__) \ + ( ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_SINGLE) \ + || ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_CONTINUOUS) \ + ) + +#define IS_LL_ADC_REG_DMA_TRANSFER(__REG_DMA_TRANSFER__) \ + ( ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_NONE) \ + || ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_LIMITED) \ + || ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) \ + ) + +#define IS_LL_ADC_REG_FLAG_EOC_SELECTION(__REG_FLAG_EOC_SELECTION__) \ + ( ((__REG_FLAG_EOC_SELECTION__) == LL_ADC_REG_FLAG_EOC_SEQUENCE_CONV) \ + || ((__REG_FLAG_EOC_SELECTION__) == LL_ADC_REG_FLAG_EOC_UNITARY_CONV) \ + ) + +#define IS_LL_ADC_REG_SEQ_SCAN_LENGTH(__REG_SEQ_SCAN_LENGTH__) \ + ( ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_DISABLE) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS) \ + || ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS) \ + ) + +#define IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(__REG_SEQ_DISCONT_MODE__) \ + ( ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_DISABLE) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_1RANK) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_2RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_3RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_4RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_5RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_6RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_7RANKS) \ + || ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_8RANKS) \ + ) + +/* Check of parameters for configuration of ADC hierarchical scope: */ +/* ADC group injected */ +#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \ + ( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH2) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_CH1) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_CH2) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_CH3) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_TRGO) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH2) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH3) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \ + || ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \ + ) + +#define IS_LL_ADC_INJ_TRIG_EXT_EDGE(__INJ_TRIG_EXT_EDGE__) \ + ( ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_RISING) \ + || ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_FALLING) \ + || ((__INJ_TRIG_EXT_EDGE__) == LL_ADC_INJ_TRIG_EXT_RISINGFALLING) \ + ) + +#define IS_LL_ADC_INJ_TRIG_AUTO(__INJ_TRIG_AUTO__) \ + ( ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_INDEPENDENT) \ + || ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_FROM_GRP_REGULAR) \ + ) + +#define IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(__INJ_SEQ_SCAN_LENGTH__) \ + ( ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_DISABLE) \ + || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS) \ + || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS) \ + || ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS) \ + ) + +#define IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(__INJ_SEQ_DISCONT_MODE__) \ + ( ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_DISABLE) \ + || ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_1RANK) \ + ) + +#if defined(ADC_MULTIMODE_SUPPORT) +/* Check of parameters for configuration of ADC hierarchical scope: */ +/* multimode. */ +#if defined(ADC3) +#define IS_LL_ADC_MULTI_MODE(__MULTI_MODE__) \ + ( ((__MULTI_MODE__) == LL_ADC_MULTI_INDEPENDENT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_ALTERN) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_SIM) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_REG_SIM_INJ_ALT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_INJ_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_REG_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_REG_INTERL) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_TRIPLE_INJ_ALTERN) \ + ) +#else +#define IS_LL_ADC_MULTI_MODE(__MULTI_MODE__) \ + ( ((__MULTI_MODE__) == LL_ADC_MULTI_INDEPENDENT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_SIMULT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_ALTERN) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT) \ + || ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INT_INJ_SIM) \ + ) +#endif + +#define IS_LL_ADC_MULTI_DMA_TRANSFER(__MULTI_DMA_TRANSFER__) \ + ( ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_EACH_ADC) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_LIMIT_1) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_LIMIT_2) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_LIMIT_3) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_UNLMT_1) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_UNLMT_2) \ + || ((__MULTI_DMA_TRANSFER__) == LL_ADC_MULTI_REG_DMA_UNLMT_3) \ + ) + +#define IS_LL_ADC_MULTI_TWOSMP_DELAY(__MULTI_TWOSMP_DELAY__) \ + ( ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_6CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_7CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_8CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_9CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_10CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_11CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_12CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_13CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_14CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_15CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_16CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_17CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_18CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_19CYCLES) \ + || ((__MULTI_TWOSMP_DELAY__) == LL_ADC_MULTI_TWOSMP_DELAY_20CYCLES) \ + ) + +#define IS_LL_ADC_MULTI_MASTER_SLAVE(__MULTI_MASTER_SLAVE__) \ + ( ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER) \ + || ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_SLAVE) \ + || ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER_SLAVE) \ + ) + +#endif /* ADC_MULTIMODE_SUPPORT */ +/** + * @} + */ + + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup ADC_LL_Exported_Functions + * @{ + */ + +/** @addtogroup ADC_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize registers of all ADC instances belonging to + * the same ADC common instance to their default reset values. + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC common registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_ADC_CommonDeInit(ADC_Common_TypeDef *ADCxy_COMMON) +{ + /* Check the parameters */ + assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON)); + + + /* Force reset of ADC clock (core clock) */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ADC); + + /* Release reset of ADC clock (core clock) */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ADC); + + return SUCCESS; +} + +/** + * @brief Initialize some features of ADC common parameters + * (all ADC instances belonging to the same ADC common instance) + * and multimode (for devices with several ADC instances available). + * @note The setting of ADC common parameters is conditioned to + * ADC instances state: + * All ADC instances belonging to the same ADC common instance + * must be disabled. + * @param ADCxy_COMMON ADC common instance + * (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() ) + * @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC common registers are initialized + * - ERROR: ADC common registers are not initialized + */ +ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON)); + assert_param(IS_LL_ADC_COMMON_CLOCK(ADC_CommonInitStruct->CommonClock)); + +#if defined(ADC_MULTIMODE_SUPPORT) + assert_param(IS_LL_ADC_MULTI_MODE(ADC_CommonInitStruct->Multimode)); + if (ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) + { + assert_param(IS_LL_ADC_MULTI_DMA_TRANSFER(ADC_CommonInitStruct->MultiDMATransfer)); + assert_param(IS_LL_ADC_MULTI_TWOSMP_DELAY(ADC_CommonInitStruct->MultiTwoSamplingDelay)); + } +#endif /* ADC_MULTIMODE_SUPPORT */ + + /* Note: Hardware constraint (refer to description of functions */ + /* "LL_ADC_SetCommonXXX()" and "LL_ADC_SetMultiXXX()"): */ + /* On this STM32 series, setting of these features is conditioned to */ + /* ADC state: */ + /* All ADC instances of the ADC common group must be disabled. */ + if (__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(ADCxy_COMMON) == 0UL) + { + /* Configuration of ADC hierarchical scope: */ + /* - common to several ADC */ + /* (all ADC instances belonging to the same ADC common instance) */ + /* - Set ADC clock (conversion clock) */ + /* - multimode (if several ADC instances available on the */ + /* selected device) */ + /* - Set ADC multimode configuration */ + /* - Set ADC multimode DMA transfer */ + /* - Set ADC multimode: delay between 2 sampling phases */ +#if defined(ADC_MULTIMODE_SUPPORT) + if (ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT) + { + MODIFY_REG(ADCxy_COMMON->CCR, + ADC_CCR_ADCPRE + | ADC_CCR_MULTI + | ADC_CCR_DMA + | ADC_CCR_DDS + | ADC_CCR_DELAY + , + ADC_CommonInitStruct->CommonClock + | ADC_CommonInitStruct->Multimode + | ADC_CommonInitStruct->MultiDMATransfer + | ADC_CommonInitStruct->MultiTwoSamplingDelay + ); + } + else + { + MODIFY_REG(ADCxy_COMMON->CCR, + ADC_CCR_ADCPRE + | ADC_CCR_MULTI + | ADC_CCR_DMA + | ADC_CCR_DDS + | ADC_CCR_DELAY + , + ADC_CommonInitStruct->CommonClock + | LL_ADC_MULTI_INDEPENDENT + ); + } +#else + LL_ADC_SetCommonClock(ADCxy_COMMON, ADC_CommonInitStruct->CommonClock); +#endif + } + else + { + /* Initialization error: One or several ADC instances belonging to */ + /* the same ADC common instance are not disabled. */ + status = ERROR; + } + + return status; +} + +/** + * @brief Set each @ref LL_ADC_CommonInitTypeDef field to default value. + * @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct) +{ + /* Set ADC_CommonInitStruct fields to default values */ + /* Set fields of ADC common */ + /* (all ADC instances belonging to the same ADC common instance) */ + ADC_CommonInitStruct->CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV2; + +#if defined(ADC_MULTIMODE_SUPPORT) + /* Set fields of ADC multimode */ + ADC_CommonInitStruct->Multimode = LL_ADC_MULTI_INDEPENDENT; + ADC_CommonInitStruct->MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC; + ADC_CommonInitStruct->MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES; +#endif /* ADC_MULTIMODE_SUPPORT */ +} + +/** + * @brief De-initialize registers of the selected ADC instance + * to their default reset values. + * @note To reset all ADC instances quickly (perform a hard reset), + * use function @ref LL_ADC_CommonDeInit(). + * @param ADCx ADC instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC registers are de-initialized + * - ERROR: ADC registers are not de-initialized + */ +ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + + /* Disable ADC instance if not already disabled. */ + if (LL_ADC_IsEnabled(ADCx) == 1UL) + { + /* Set ADC group regular trigger source to SW start to ensure to not */ + /* have an external trigger event occurring during the conversion stop */ + /* ADC disable process. */ + LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE); + + /* Set ADC group injected trigger source to SW start to ensure to not */ + /* have an external trigger event occurring during the conversion stop */ + /* ADC disable process. */ + LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE); + + /* Disable the ADC instance */ + LL_ADC_Disable(ADCx); + } + + /* Check whether ADC state is compliant with expected state */ + /* (hardware requirements of bits state to reset registers below) */ + if (READ_BIT(ADCx->CR2, ADC_CR2_ADON) == 0UL) + { + /* ========== Reset ADC registers ========== */ + /* Reset register SR */ + CLEAR_BIT(ADCx->SR, + (LL_ADC_FLAG_STRT + | LL_ADC_FLAG_JSTRT + | LL_ADC_FLAG_EOCS + | LL_ADC_FLAG_OVR + | LL_ADC_FLAG_JEOS + | LL_ADC_FLAG_AWD1) + ); + + /* Reset register CR1 */ + CLEAR_BIT(ADCx->CR1, + (ADC_CR1_OVRIE | ADC_CR1_RES | ADC_CR1_AWDEN + | ADC_CR1_JAWDEN + | ADC_CR1_DISCNUM | ADC_CR1_JDISCEN | ADC_CR1_DISCEN + | ADC_CR1_JAUTO | ADC_CR1_AWDSGL | ADC_CR1_SCAN + | ADC_CR1_JEOCIE | ADC_CR1_AWDIE | ADC_CR1_EOCIE + | ADC_CR1_AWDCH) + ); + + /* Reset register CR2 */ + CLEAR_BIT(ADCx->CR2, + (ADC_CR2_SWSTART | ADC_CR2_EXTEN | ADC_CR2_EXTSEL + | ADC_CR2_JSWSTART | ADC_CR2_JEXTEN | ADC_CR2_JEXTSEL + | ADC_CR2_ALIGN | ADC_CR2_EOCS + | ADC_CR2_DDS | ADC_CR2_DMA + | ADC_CR2_CONT | ADC_CR2_ADON) + ); + + /* Reset register SMPR1 */ + CLEAR_BIT(ADCx->SMPR1, + (ADC_SMPR1_SMP18 | ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 + | ADC_SMPR1_SMP15 | ADC_SMPR1_SMP14 | ADC_SMPR1_SMP13 + | ADC_SMPR1_SMP12 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP10) + ); + + /* Reset register SMPR2 */ + CLEAR_BIT(ADCx->SMPR2, + (ADC_SMPR2_SMP9 + | ADC_SMPR2_SMP8 | ADC_SMPR2_SMP7 | ADC_SMPR2_SMP6 + | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP4 | ADC_SMPR2_SMP3 + | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP1 | ADC_SMPR2_SMP0) + ); + + /* Reset register JOFR1 */ + CLEAR_BIT(ADCx->JOFR1, ADC_JOFR1_JOFFSET1); + /* Reset register JOFR2 */ + CLEAR_BIT(ADCx->JOFR2, ADC_JOFR2_JOFFSET2); + /* Reset register JOFR3 */ + CLEAR_BIT(ADCx->JOFR3, ADC_JOFR3_JOFFSET3); + /* Reset register JOFR4 */ + CLEAR_BIT(ADCx->JOFR4, ADC_JOFR4_JOFFSET4); + + /* Reset register HTR */ + SET_BIT(ADCx->HTR, ADC_HTR_HT); + /* Reset register LTR */ + CLEAR_BIT(ADCx->LTR, ADC_LTR_LT); + + /* Reset register SQR1 */ + CLEAR_BIT(ADCx->SQR1, + (ADC_SQR1_L + | ADC_SQR1_SQ16 + | ADC_SQR1_SQ15 | ADC_SQR1_SQ14 | ADC_SQR1_SQ13) + ); + + /* Reset register SQR2 */ + CLEAR_BIT(ADCx->SQR2, + (ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 + | ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7) + ); + + /* Reset register SQR3 */ + CLEAR_BIT(ADCx->SQR3, + (ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 + | ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1) + ); + + /* Reset register JSQR */ + CLEAR_BIT(ADCx->JSQR, + (ADC_JSQR_JL + | ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 + | ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1) + ); + + /* Reset register DR */ + /* bits in access mode read only, no direct reset applicable */ + + /* Reset registers JDR1, JDR2, JDR3, JDR4 */ + /* bits in access mode read only, no direct reset applicable */ + + /* Reset register CCR */ + CLEAR_BIT(ADC->CCR, ADC_CCR_TSVREFE | ADC_CCR_ADCPRE); + } + + return status; +} + +/** + * @brief Initialize some features of ADC instance. + * @note These parameters have an impact on ADC scope: ADC instance. + * Affects both group regular and group injected (availability + * of ADC group injected depends on STM32 families). + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Instance . + * @note The setting of these parameters by function @ref LL_ADC_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + * @note After using this function, some other features must be configured + * using LL unitary functions. + * The minimum configuration remaining to be done is: + * - Set ADC group regular or group injected sequencer: + * map channel on the selected sequencer rank. + * Refer to function @ref LL_ADC_REG_SetSequencerRanks(). + * - Set ADC channel sampling time + * Refer to function LL_ADC_SetChannelSamplingTime(); + * @param ADCx ADC instance + * @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC registers are initialized + * - ERROR: ADC registers are not initialized + */ +ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + + assert_param(IS_LL_ADC_RESOLUTION(ADC_InitStruct->Resolution)); + assert_param(IS_LL_ADC_DATA_ALIGN(ADC_InitStruct->DataAlignment)); + assert_param(IS_LL_ADC_SCAN_SELECTION(ADC_InitStruct->SequencersScanMode)); + + /* Note: Hardware constraint (refer to description of this function): */ + /* ADC instance must be disabled. */ + if (LL_ADC_IsEnabled(ADCx) == 0UL) + { + /* Configuration of ADC hierarchical scope: */ + /* - ADC instance */ + /* - Set ADC data resolution */ + /* - Set ADC conversion data alignment */ + MODIFY_REG(ADCx->CR1, + ADC_CR1_RES + | ADC_CR1_SCAN + , + ADC_InitStruct->Resolution + | ADC_InitStruct->SequencersScanMode + ); + + MODIFY_REG(ADCx->CR2, + ADC_CR2_ALIGN + , + ADC_InitStruct->DataAlignment + ); + + } + else + { + /* Initialization error: ADC instance is not disabled. */ + status = ERROR; + } + return status; +} + +/** + * @brief Set each @ref LL_ADC_InitTypeDef field to default value. + * @param ADC_InitStruct Pointer to a @ref LL_ADC_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_ADC_StructInit(LL_ADC_InitTypeDef *ADC_InitStruct) +{ + /* Set ADC_InitStruct fields to default values */ + /* Set fields of ADC instance */ + ADC_InitStruct->Resolution = LL_ADC_RESOLUTION_12B; + ADC_InitStruct->DataAlignment = LL_ADC_DATA_ALIGN_RIGHT; + + /* Enable scan mode to have a generic behavior with ADC of other */ + /* STM32 families, without this setting available: */ + /* ADC group regular sequencer and ADC group injected sequencer depend */ + /* only of their own configuration. */ + ADC_InitStruct->SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE; + +} + +/** + * @brief Initialize some features of ADC group regular. + * @note These parameters have an impact on ADC scope: ADC group regular. + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Group_Regular + * (functions with prefix "REG"). + * @note The setting of these parameters by function @ref LL_ADC_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + * @note After using this function, other features must be configured + * using LL unitary functions. + * The minimum configuration remaining to be done is: + * - Set ADC group regular or group injected sequencer: + * map channel on the selected sequencer rank. + * Refer to function @ref LL_ADC_REG_SetSequencerRanks(). + * - Set ADC channel sampling time + * Refer to function LL_ADC_SetChannelSamplingTime(); + * @param ADCx ADC instance + * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC registers are initialized + * - ERROR: ADC registers are not initialized + */ +ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource)); + assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(ADC_REG_InitStruct->SequencerLength)); + if (ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont)); + } + assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode)); + assert_param(IS_LL_ADC_REG_DMA_TRANSFER(ADC_REG_InitStruct->DMATransfer)); + + /* ADC group regular continuous mode and discontinuous mode */ + /* can not be enabled simultenaeously */ + assert_param((ADC_REG_InitStruct->ContinuousMode == LL_ADC_REG_CONV_SINGLE) + || (ADC_REG_InitStruct->SequencerDiscont == LL_ADC_REG_SEQ_DISCONT_DISABLE)); + + /* Note: Hardware constraint (refer to description of this function): */ + /* ADC instance must be disabled. */ + if (LL_ADC_IsEnabled(ADCx) == 0UL) + { + /* Configuration of ADC hierarchical scope: */ + /* - ADC group regular */ + /* - Set ADC group regular trigger source */ + /* - Set ADC group regular sequencer length */ + /* - Set ADC group regular sequencer discontinuous mode */ + /* - Set ADC group regular continuous mode */ + /* - Set ADC group regular conversion data transfer: no transfer or */ + /* transfer by DMA, and DMA requests mode */ + /* Note: On this STM32 series, ADC trigger edge is set when starting */ + /* ADC conversion. */ + /* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */ + if (ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + MODIFY_REG(ADCx->CR1, + ADC_CR1_DISCEN + | ADC_CR1_DISCNUM + , + ADC_REG_InitStruct->SequencerDiscont + ); + } + else + { + MODIFY_REG(ADCx->CR1, + ADC_CR1_DISCEN + | ADC_CR1_DISCNUM + , + LL_ADC_REG_SEQ_DISCONT_DISABLE + ); + } + + MODIFY_REG(ADCx->CR2, + ADC_CR2_EXTSEL + | ADC_CR2_EXTEN + | ADC_CR2_CONT + | ADC_CR2_DMA + | ADC_CR2_DDS + , + (ADC_REG_InitStruct->TriggerSource & ADC_CR2_EXTSEL) + | ADC_REG_InitStruct->ContinuousMode + | ADC_REG_InitStruct->DMATransfer + ); + + /* Set ADC group regular sequencer length and scan direction */ + /* Note: Hardware constraint (refer to description of this function): */ + /* Note: If ADC instance feature scan mode is disabled */ + /* (refer to ADC instance initialization structure */ + /* parameter @ref SequencersScanMode */ + /* or function @ref LL_ADC_SetSequencersScanMode() ), */ + /* this parameter is discarded. */ + LL_ADC_REG_SetSequencerLength(ADCx, ADC_REG_InitStruct->SequencerLength); + } + else + { + /* Initialization error: ADC instance is not disabled. */ + status = ERROR; + } + return status; +} + +/** + * @brief Set each @ref LL_ADC_REG_InitTypeDef field to default value. + * @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct) +{ + /* Set ADC_REG_InitStruct fields to default values */ + /* Set fields of ADC group regular */ + /* Note: On this STM32 series, ADC trigger edge is set when starting */ + /* ADC conversion. */ + /* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */ + ADC_REG_InitStruct->TriggerSource = LL_ADC_REG_TRIG_SOFTWARE; + ADC_REG_InitStruct->SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE; + ADC_REG_InitStruct->SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE; + ADC_REG_InitStruct->ContinuousMode = LL_ADC_REG_CONV_SINGLE; + ADC_REG_InitStruct->DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE; +} + +/** + * @brief Initialize some features of ADC group injected. + * @note These parameters have an impact on ADC scope: ADC group injected. + * Refer to corresponding unitary functions into + * @ref ADC_LL_EF_Configuration_ADC_Group_Regular + * (functions with prefix "INJ"). + * @note The setting of these parameters by function @ref LL_ADC_Init() + * is conditioned to ADC state: + * ADC instance must be disabled. + * This condition is applied to all ADC features, for efficiency + * and compatibility over all STM32 families. However, the different + * features can be set under different ADC state conditions + * (setting possible with ADC enabled without conversion on going, + * ADC enabled with conversion on going, ...) + * Each feature can be updated afterwards with a unitary function + * and potentially with ADC in a different state than disabled, + * refer to description of each function for setting + * conditioned to ADC state. + * @note After using this function, other features must be configured + * using LL unitary functions. + * The minimum configuration remaining to be done is: + * - Set ADC group injected sequencer: + * map channel on the selected sequencer rank. + * Refer to function @ref LL_ADC_INJ_SetSequencerRanks(). + * - Set ADC channel sampling time + * Refer to function LL_ADC_SetChannelSamplingTime(); + * @param ADCx ADC instance + * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ADC registers are initialized + * - ERROR: ADC registers are not initialized + */ +ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_ADC_ALL_INSTANCE(ADCx)); + assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource)); + assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength)); + if (ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE) + { + assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont)); + } + assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto)); + + /* Note: Hardware constraint (refer to description of this function): */ + /* ADC instance must be disabled. */ + if (LL_ADC_IsEnabled(ADCx) == 0UL) + { + /* Configuration of ADC hierarchical scope: */ + /* - ADC group injected */ + /* - Set ADC group injected trigger source */ + /* - Set ADC group injected sequencer length */ + /* - Set ADC group injected sequencer discontinuous mode */ + /* - Set ADC group injected conversion trigger: independent or */ + /* from ADC group regular */ + /* Note: On this STM32 series, ADC trigger edge is set when starting */ + /* ADC conversion. */ + /* Refer to function @ref LL_ADC_INJ_StartConversionExtTrig(). */ + if (ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE) + { + MODIFY_REG(ADCx->CR1, + ADC_CR1_JDISCEN + | ADC_CR1_JAUTO + , + ADC_INJ_InitStruct->SequencerDiscont + | ADC_INJ_InitStruct->TrigAuto + ); + } + else + { + MODIFY_REG(ADCx->CR1, + ADC_CR1_JDISCEN + | ADC_CR1_JAUTO + , + LL_ADC_REG_SEQ_DISCONT_DISABLE + | ADC_INJ_InitStruct->TrigAuto + ); + } + + MODIFY_REG(ADCx->CR2, + ADC_CR2_JEXTSEL + | ADC_CR2_JEXTEN + , + (ADC_INJ_InitStruct->TriggerSource & ADC_CR2_JEXTSEL) + ); + + /* Note: Hardware constraint (refer to description of this function): */ + /* Note: If ADC instance feature scan mode is disabled */ + /* (refer to ADC instance initialization structure */ + /* parameter @ref SequencersScanMode */ + /* or function @ref LL_ADC_SetSequencersScanMode() ), */ + /* this parameter is discarded. */ + LL_ADC_INJ_SetSequencerLength(ADCx, ADC_INJ_InitStruct->SequencerLength); + } + else + { + /* Initialization error: ADC instance is not disabled. */ + status = ERROR; + } + return status; +} + +/** + * @brief Set each @ref LL_ADC_INJ_InitTypeDef field to default value. + * @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct) +{ + /* Set ADC_INJ_InitStruct fields to default values */ + /* Set fields of ADC group injected */ + ADC_INJ_InitStruct->TriggerSource = LL_ADC_INJ_TRIG_SOFTWARE; + ADC_INJ_InitStruct->SequencerLength = LL_ADC_INJ_SEQ_SCAN_DISABLE; + ADC_INJ_InitStruct->SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE; + ADC_INJ_InitStruct->TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ADC1 || ADC2 || ADC3 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c new file mode 100644 index 0000000..1138793 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_crc.c @@ -0,0 +1,103 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_crc.c + * @author MCD Application Team + * @brief CRC LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_crc.h" +#include "stm32f4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (CRC) + +/** @addtogroup CRC_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup CRC_LL_Exported_Functions + * @{ + */ + +/** @addtogroup CRC_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize CRC registers (Registers restored to their default values). + * @param CRCx CRC Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: CRC registers are de-initialized + * - ERROR: CRC registers are not de-initialized + */ +ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_CRC_ALL_INSTANCE(CRCx)); + + if (CRCx == CRC) + { + /* Force CRC reset */ + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_CRC); + + /* Release CRC reset */ + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_CRC); + } + else + { + status = ERROR; + } + + return (status); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (CRC) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c new file mode 100644 index 0000000..0a5c2ff --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dac.c @@ -0,0 +1,280 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_dac.c + * @author MCD Application Team + * @brief DAC LL module driver + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_dac.h" +#include "stm32f4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(DAC) + +/** @addtogroup DAC_LL DAC + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ + +/** @addtogroup DAC_LL_Private_Macros + * @{ + */ +#if defined(DAC_CHANNEL2_SUPPORT) +#define IS_LL_DAC_CHANNEL(__DACX__, __DAC_CHANNEL__) \ + ( \ + ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \ + || ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_2) \ + ) +#else +#define IS_LL_DAC_CHANNEL(__DACX__, __DAC_CHANNEL__) \ + ( \ + ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \ + ) +#endif /* DAC_CHANNEL2_SUPPORT */ + +#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \ + ( ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \ + || ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \ + ) + +#define IS_LL_DAC_WAVE_AUTO_GENER_MODE(__WAVE_AUTO_GENERATION_MODE__) \ + ( ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NONE) \ + || ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \ + || ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \ + ) + +#define IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(__WAVE_AUTO_GENERATION_MODE__, __WAVE_AUTO_GENERATION_CONFIG__) \ + ( (((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \ + && ( ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BIT0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS1_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS2_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS3_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS4_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS5_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS6_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS7_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS8_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS9_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS10_0) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS11_0)) \ + ) \ + ||(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \ + && ( ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_3) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_7) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_15) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_31) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_63) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_127) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_255) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_511) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1023) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_2047) \ + || ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_4095)) \ + ) \ + ) + +#define IS_LL_DAC_OUTPUT_BUFFER(__OUTPUT_BUFFER__) \ + ( ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_ENABLE) \ + || ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_DISABLE) \ + ) + +/** + * @} + */ + + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DAC_LL_Exported_Functions + * @{ + */ + +/** @addtogroup DAC_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize registers of the selected DAC instance + * to their default reset values. + * @param DACx DAC instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DAC registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_DAC_DeInit(DAC_TypeDef *DACx) +{ + /* Check the parameters */ + assert_param(IS_DAC_ALL_INSTANCE(DACx)); + + /* Force reset of DAC clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_DAC1); + + /* Release reset of DAC clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_DAC1); + + return SUCCESS; +} + +/** + * @brief Initialize some features of DAC channel. + * @note @ref LL_DAC_Init() aims to ease basic configuration of a DAC channel. + * Leaving it ready to be enabled and output: + * a level by calling one of + * @ref LL_DAC_ConvertData12RightAligned + * @ref LL_DAC_ConvertData12LeftAligned + * @ref LL_DAC_ConvertData8RightAligned + * or one of the supported autogenerated wave. + * @note This function allows configuration of: + * - Output mode + * - Trigger + * - Wave generation + * @note The setting of these parameters by function @ref LL_DAC_Init() + * is conditioned to DAC state: + * DAC channel must be disabled. + * @param DACx DAC instance + * @param DAC_Channel This parameter can be one of the following values: + * @arg @ref LL_DAC_CHANNEL_1 + * @arg @ref LL_DAC_CHANNEL_2 (1) + * + * (1) On this STM32 serie, parameter not available on all devices. + * Refer to device datasheet for channels availability. + * @param DAC_InitStruct Pointer to a @ref LL_DAC_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DAC registers are initialized + * - ERROR: DAC registers are not initialized + */ +ErrorStatus LL_DAC_Init(DAC_TypeDef *DACx, uint32_t DAC_Channel, LL_DAC_InitTypeDef *DAC_InitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_DAC_ALL_INSTANCE(DACx)); + assert_param(IS_LL_DAC_CHANNEL(DACx, DAC_Channel)); + assert_param(IS_LL_DAC_TRIGGER_SOURCE(DAC_InitStruct->TriggerSource)); + assert_param(IS_LL_DAC_OUTPUT_BUFFER(DAC_InitStruct->OutputBuffer)); + assert_param(IS_LL_DAC_WAVE_AUTO_GENER_MODE(DAC_InitStruct->WaveAutoGeneration)); + if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE) + { + assert_param(IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(DAC_InitStruct->WaveAutoGeneration, + DAC_InitStruct->WaveAutoGenerationConfig)); + } + + /* Note: Hardware constraint (refer to description of this function) */ + /* DAC instance must be disabled. */ + if (LL_DAC_IsEnabled(DACx, DAC_Channel) == 0UL) + { + /* Configuration of DAC channel: */ + /* - TriggerSource */ + /* - WaveAutoGeneration */ + /* - OutputBuffer */ + /* - OutputMode */ + if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE) + { + MODIFY_REG(DACx->CR, + (DAC_CR_TSEL1 + | DAC_CR_WAVE1 + | DAC_CR_MAMP1 + | DAC_CR_BOFF1 + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + , + (DAC_InitStruct->TriggerSource + | DAC_InitStruct->WaveAutoGeneration + | DAC_InitStruct->WaveAutoGenerationConfig + | DAC_InitStruct->OutputBuffer + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); + } + else + { + MODIFY_REG(DACx->CR, + (DAC_CR_TSEL1 + | DAC_CR_WAVE1 + | DAC_CR_BOFF1 + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + , + (DAC_InitStruct->TriggerSource + | LL_DAC_WAVE_AUTO_GENERATION_NONE + | DAC_InitStruct->OutputBuffer + ) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK) + ); + } + } + else + { + /* Initialization error: DAC instance is not disabled. */ + status = ERROR; + } + return status; +} + +/** + * @brief Set each @ref LL_DAC_InitTypeDef field to default value. + * @param DAC_InitStruct pointer to a @ref LL_DAC_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_DAC_StructInit(LL_DAC_InitTypeDef *DAC_InitStruct) +{ + /* Set DAC_InitStruct fields to default values */ + DAC_InitStruct->TriggerSource = LL_DAC_TRIG_SOFTWARE; + DAC_InitStruct->WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE; + /* Note: Parameter discarded if wave auto generation is disabled, */ + /* set anyway to its default value. */ + DAC_InitStruct->WaveAutoGenerationConfig = LL_DAC_NOISE_LFSR_UNMASK_BIT0; + DAC_InitStruct->OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DAC */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c new file mode 100644 index 0000000..a83c086 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c @@ -0,0 +1,423 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_dma.c + * @author MCD Application Team + * @brief DMA LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_dma.h" +#include "stm32f4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (DMA1) || defined (DMA2) + +/** @defgroup DMA_LL DMA + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup DMA_LL_Private_Macros + * @{ + */ +#define IS_LL_DMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \ + ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \ + ((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY)) + +#define IS_LL_DMA_MODE(__VALUE__) (((__VALUE__) == LL_DMA_MODE_NORMAL) || \ + ((__VALUE__) == LL_DMA_MODE_CIRCULAR) || \ + ((__VALUE__) == LL_DMA_MODE_PFCTRL)) + +#define IS_LL_DMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \ + ((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT)) + +#define IS_LL_DMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \ + ((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT)) + +#define IS_LL_DMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE) || \ + ((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD) || \ + ((__VALUE__) == LL_DMA_PDATAALIGN_WORD)) + +#define IS_LL_DMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE) || \ + ((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD) || \ + ((__VALUE__) == LL_DMA_MDATAALIGN_WORD)) + +#define IS_LL_DMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU) + +#define IS_LL_DMA_CHANNEL(__VALUE__) (((__VALUE__) == LL_DMA_CHANNEL_0) || \ + ((__VALUE__) == LL_DMA_CHANNEL_1) || \ + ((__VALUE__) == LL_DMA_CHANNEL_2) || \ + ((__VALUE__) == LL_DMA_CHANNEL_3) || \ + ((__VALUE__) == LL_DMA_CHANNEL_4) || \ + ((__VALUE__) == LL_DMA_CHANNEL_5) || \ + ((__VALUE__) == LL_DMA_CHANNEL_6) || \ + ((__VALUE__) == LL_DMA_CHANNEL_7)) + +#define IS_LL_DMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_DMA_PRIORITY_LOW) || \ + ((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \ + ((__VALUE__) == LL_DMA_PRIORITY_HIGH) || \ + ((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH)) + +#define IS_LL_DMA_ALL_STREAM_INSTANCE(INSTANCE, STREAM) ((((INSTANCE) == DMA1) && \ + (((STREAM) == LL_DMA_STREAM_0) || \ + ((STREAM) == LL_DMA_STREAM_1) || \ + ((STREAM) == LL_DMA_STREAM_2) || \ + ((STREAM) == LL_DMA_STREAM_3) || \ + ((STREAM) == LL_DMA_STREAM_4) || \ + ((STREAM) == LL_DMA_STREAM_5) || \ + ((STREAM) == LL_DMA_STREAM_6) || \ + ((STREAM) == LL_DMA_STREAM_7) || \ + ((STREAM) == LL_DMA_STREAM_ALL))) ||\ + (((INSTANCE) == DMA2) && \ + (((STREAM) == LL_DMA_STREAM_0) || \ + ((STREAM) == LL_DMA_STREAM_1) || \ + ((STREAM) == LL_DMA_STREAM_2) || \ + ((STREAM) == LL_DMA_STREAM_3) || \ + ((STREAM) == LL_DMA_STREAM_4) || \ + ((STREAM) == LL_DMA_STREAM_5) || \ + ((STREAM) == LL_DMA_STREAM_6) || \ + ((STREAM) == LL_DMA_STREAM_7) || \ + ((STREAM) == LL_DMA_STREAM_ALL)))) + +#define IS_LL_DMA_FIFO_MODE_STATE(STATE) (((STATE) == LL_DMA_FIFOMODE_DISABLE ) || \ + ((STATE) == LL_DMA_FIFOMODE_ENABLE)) + +#define IS_LL_DMA_FIFO_THRESHOLD(THRESHOLD) (((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_1_4) || \ + ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_1_2) || \ + ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_3_4) || \ + ((THRESHOLD) == LL_DMA_FIFOTHRESHOLD_FULL)) + +#define IS_LL_DMA_MEMORY_BURST(BURST) (((BURST) == LL_DMA_MBURST_SINGLE) || \ + ((BURST) == LL_DMA_MBURST_INC4) || \ + ((BURST) == LL_DMA_MBURST_INC8) || \ + ((BURST) == LL_DMA_MBURST_INC16)) + +#define IS_LL_DMA_PERIPHERAL_BURST(BURST) (((BURST) == LL_DMA_PBURST_SINGLE) || \ + ((BURST) == LL_DMA_PBURST_INC4) || \ + ((BURST) == LL_DMA_PBURST_INC8) || \ + ((BURST) == LL_DMA_PBURST_INC16)) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DMA_LL_Exported_Functions + * @{ + */ + +/** @addtogroup DMA_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the DMA registers to their default reset values. + * @param DMAx DMAx Instance + * @param Stream This parameter can be one of the following values: + * @arg @ref LL_DMA_STREAM_0 + * @arg @ref LL_DMA_STREAM_1 + * @arg @ref LL_DMA_STREAM_2 + * @arg @ref LL_DMA_STREAM_3 + * @arg @ref LL_DMA_STREAM_4 + * @arg @ref LL_DMA_STREAM_5 + * @arg @ref LL_DMA_STREAM_6 + * @arg @ref LL_DMA_STREAM_7 + * @arg @ref LL_DMA_STREAM_ALL + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DMA registers are de-initialized + * - ERROR: DMA registers are not de-initialized + */ +uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Stream) +{ + DMA_Stream_TypeDef *tmp = (DMA_Stream_TypeDef *)DMA1_Stream0; + ErrorStatus status = SUCCESS; + + /* Check the DMA Instance DMAx and Stream parameters*/ + assert_param(IS_LL_DMA_ALL_STREAM_INSTANCE(DMAx, Stream)); + + if (Stream == LL_DMA_STREAM_ALL) + { + if (DMAx == DMA1) + { + /* Force reset of DMA clock */ + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA1); + + /* Release reset of DMA clock */ + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA1); + } + else if (DMAx == DMA2) + { + /* Force reset of DMA clock */ + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA2); + + /* Release reset of DMA clock */ + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA2); + } + else + { + status = ERROR; + } + } + else + { + /* Disable the selected Stream */ + LL_DMA_DisableStream(DMAx,Stream); + + /* Get the DMA Stream Instance */ + tmp = (DMA_Stream_TypeDef *)(__LL_DMA_GET_STREAM_INSTANCE(DMAx, Stream)); + + /* Reset DMAx_Streamy configuration register */ + LL_DMA_WriteReg(tmp, CR, 0U); + + /* Reset DMAx_Streamy remaining bytes register */ + LL_DMA_WriteReg(tmp, NDTR, 0U); + + /* Reset DMAx_Streamy peripheral address register */ + LL_DMA_WriteReg(tmp, PAR, 0U); + + /* Reset DMAx_Streamy memory address register */ + LL_DMA_WriteReg(tmp, M0AR, 0U); + + /* Reset DMAx_Streamy memory address register */ + LL_DMA_WriteReg(tmp, M1AR, 0U); + + /* Reset DMAx_Streamy FIFO control register */ + LL_DMA_WriteReg(tmp, FCR, 0x00000021U); + + /* Reset Channel register field for DMAx Stream*/ + LL_DMA_SetChannelSelection(DMAx, Stream, LL_DMA_CHANNEL_0); + + if(Stream == LL_DMA_STREAM_0) + { + /* Reset the Stream0 pending flags */ + DMAx->LIFCR = 0x0000003FU; + } + else if(Stream == LL_DMA_STREAM_1) + { + /* Reset the Stream1 pending flags */ + DMAx->LIFCR = 0x00000F40U; + } + else if(Stream == LL_DMA_STREAM_2) + { + /* Reset the Stream2 pending flags */ + DMAx->LIFCR = 0x003F0000U; + } + else if(Stream == LL_DMA_STREAM_3) + { + /* Reset the Stream3 pending flags */ + DMAx->LIFCR = 0x0F400000U; + } + else if(Stream == LL_DMA_STREAM_4) + { + /* Reset the Stream4 pending flags */ + DMAx->HIFCR = 0x0000003FU; + } + else if(Stream == LL_DMA_STREAM_5) + { + /* Reset the Stream5 pending flags */ + DMAx->HIFCR = 0x00000F40U; + } + else if(Stream == LL_DMA_STREAM_6) + { + /* Reset the Stream6 pending flags */ + DMAx->HIFCR = 0x003F0000U; + } + else if(Stream == LL_DMA_STREAM_7) + { + /* Reset the Stream7 pending flags */ + DMAx->HIFCR = 0x0F400000U; + } + else + { + status = ERROR; + } + } + + return status; +} + +/** + * @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct. + * @note To convert DMAx_Streamy Instance to DMAx Instance and Streamy, use helper macros : + * @arg @ref __LL_DMA_GET_INSTANCE + * @arg @ref __LL_DMA_GET_STREAM + * @param DMAx DMAx Instance + * @param Stream This parameter can be one of the following values: + * @arg @ref LL_DMA_STREAM_0 + * @arg @ref LL_DMA_STREAM_1 + * @arg @ref LL_DMA_STREAM_2 + * @arg @ref LL_DMA_STREAM_3 + * @arg @ref LL_DMA_STREAM_4 + * @arg @ref LL_DMA_STREAM_5 + * @arg @ref LL_DMA_STREAM_6 + * @arg @ref LL_DMA_STREAM_7 + * @param DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DMA registers are initialized + * - ERROR: Not applicable + */ +uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Stream, LL_DMA_InitTypeDef *DMA_InitStruct) +{ + /* Check the DMA Instance DMAx and Stream parameters*/ + assert_param(IS_LL_DMA_ALL_STREAM_INSTANCE(DMAx, Stream)); + + /* Check the DMA parameters from DMA_InitStruct */ + assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction)); + assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode)); + assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode)); + assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode)); + assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize)); + assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize)); + assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData)); + assert_param(IS_LL_DMA_CHANNEL(DMA_InitStruct->Channel)); + assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority)); + assert_param(IS_LL_DMA_FIFO_MODE_STATE(DMA_InitStruct->FIFOMode)); + /* Check the memory burst, peripheral burst and FIFO threshold parameters only + when FIFO mode is enabled */ + if(DMA_InitStruct->FIFOMode != LL_DMA_FIFOMODE_DISABLE) + { + assert_param(IS_LL_DMA_FIFO_THRESHOLD(DMA_InitStruct->FIFOThreshold)); + assert_param(IS_LL_DMA_MEMORY_BURST(DMA_InitStruct->MemBurst)); + assert_param(IS_LL_DMA_PERIPHERAL_BURST(DMA_InitStruct->PeriphBurst)); + } + + /*---------------------------- DMAx SxCR Configuration ------------------------ + * Configure DMAx_Streamy: data transfer direction, data transfer mode, + * peripheral and memory increment mode, + * data size alignment and priority level with parameters : + * - Direction: DMA_SxCR_DIR[1:0] bits + * - Mode: DMA_SxCR_CIRC bit + * - PeriphOrM2MSrcIncMode: DMA_SxCR_PINC bit + * - MemoryOrM2MDstIncMode: DMA_SxCR_MINC bit + * - PeriphOrM2MSrcDataSize: DMA_SxCR_PSIZE[1:0] bits + * - MemoryOrM2MDstDataSize: DMA_SxCR_MSIZE[1:0] bits + * - Priority: DMA_SxCR_PL[1:0] bits + */ + LL_DMA_ConfigTransfer(DMAx, Stream, DMA_InitStruct->Direction | \ + DMA_InitStruct->Mode | \ + DMA_InitStruct->PeriphOrM2MSrcIncMode | \ + DMA_InitStruct->MemoryOrM2MDstIncMode | \ + DMA_InitStruct->PeriphOrM2MSrcDataSize | \ + DMA_InitStruct->MemoryOrM2MDstDataSize | \ + DMA_InitStruct->Priority + ); + + if(DMA_InitStruct->FIFOMode != LL_DMA_FIFOMODE_DISABLE) + { + /*---------------------------- DMAx SxFCR Configuration ------------------------ + * Configure DMAx_Streamy: fifo mode and fifo threshold with parameters : + * - FIFOMode: DMA_SxFCR_DMDIS bit + * - FIFOThreshold: DMA_SxFCR_FTH[1:0] bits + */ + LL_DMA_ConfigFifo(DMAx, Stream, DMA_InitStruct->FIFOMode, DMA_InitStruct->FIFOThreshold); + + /*---------------------------- DMAx SxCR Configuration -------------------------- + * Configure DMAx_Streamy: memory burst transfer with parameters : + * - MemBurst: DMA_SxCR_MBURST[1:0] bits + */ + LL_DMA_SetMemoryBurstxfer(DMAx,Stream,DMA_InitStruct->MemBurst); + + /*---------------------------- DMAx SxCR Configuration -------------------------- + * Configure DMAx_Streamy: peripheral burst transfer with parameters : + * - PeriphBurst: DMA_SxCR_PBURST[1:0] bits + */ + LL_DMA_SetPeriphBurstxfer(DMAx,Stream,DMA_InitStruct->PeriphBurst); + } + + /*-------------------------- DMAx SxM0AR Configuration -------------------------- + * Configure the memory or destination base address with parameter : + * - MemoryOrM2MDstAddress: DMA_SxM0AR_M0A[31:0] bits + */ + LL_DMA_SetMemoryAddress(DMAx, Stream, DMA_InitStruct->MemoryOrM2MDstAddress); + + /*-------------------------- DMAx SxPAR Configuration --------------------------- + * Configure the peripheral or source base address with parameter : + * - PeriphOrM2MSrcAddress: DMA_SxPAR_PA[31:0] bits + */ + LL_DMA_SetPeriphAddress(DMAx, Stream, DMA_InitStruct->PeriphOrM2MSrcAddress); + + /*--------------------------- DMAx SxNDTR Configuration ------------------------- + * Configure the peripheral base address with parameter : + * - NbData: DMA_SxNDT[15:0] bits + */ + LL_DMA_SetDataLength(DMAx, Stream, DMA_InitStruct->NbData); + + /*--------------------------- DMA SxCR_CHSEL Configuration ---------------------- + * Configure the peripheral base address with parameter : + * - PeriphRequest: DMA_SxCR_CHSEL[2:0] bits + */ + LL_DMA_SetChannelSelection(DMAx, Stream, DMA_InitStruct->Channel); + + return SUCCESS; +} + +/** + * @brief Set each @ref LL_DMA_InitTypeDef field to default value. + * @param DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure. + * @retval None + */ +void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct) +{ + /* Set DMA_InitStruct fields to default values */ + DMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U; + DMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U; + DMA_InitStruct->Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; + DMA_InitStruct->Mode = LL_DMA_MODE_NORMAL; + DMA_InitStruct->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; + DMA_InitStruct->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT; + DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE; + DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE; + DMA_InitStruct->NbData = 0x00000000U; + DMA_InitStruct->Channel = LL_DMA_CHANNEL_0; + DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW; + DMA_InitStruct->FIFOMode = LL_DMA_FIFOMODE_DISABLE; + DMA_InitStruct->FIFOThreshold = LL_DMA_FIFOTHRESHOLD_1_4; + DMA_InitStruct->MemBurst = LL_DMA_MBURST_SINGLE; + DMA_InitStruct->PeriphBurst = LL_DMA_PBURST_SINGLE; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* DMA1 || DMA2 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c new file mode 100644 index 0000000..9f6c8f5 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma2d.c @@ -0,0 +1,594 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_dma2d.c + * @author MCD Application Team + * @brief DMA2D LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_dma2d.h" +#include "stm32f4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (DMA2D) + +/** @addtogroup DMA2D_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup DMA2D_LL_Private_Constants DMA2D Private Constants + * @{ + */ +#define LL_DMA2D_COLOR 0xFFU /*!< Maximum output color setting */ +#define LL_DMA2D_NUMBEROFLINES DMA2D_NLR_NL /*!< Maximum number of lines */ +#define LL_DMA2D_NUMBEROFPIXELS (DMA2D_NLR_PL >> DMA2D_NLR_PL_Pos) /*!< Maximum number of pixels per lines */ +#define LL_DMA2D_OFFSET_MAX 0x3FFFU /*!< Maximum output line offset expressed in pixels */ +#define LL_DMA2D_CLUTSIZE_MAX 0xFFU /*!< Maximum CLUT size */ +/** + * @} + */ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup DMA2D_LL_Private_Macros + * @{ + */ +#define IS_LL_DMA2D_MODE(MODE) (((MODE) == LL_DMA2D_MODE_M2M) || \ + ((MODE) == LL_DMA2D_MODE_M2M_PFC) || \ + ((MODE) == LL_DMA2D_MODE_M2M_BLEND) || \ + ((MODE) == LL_DMA2D_MODE_R2M)) + +#define IS_LL_DMA2D_OCMODE(MODE_ARGB) (((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB8888) || \ + ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_RGB888) || \ + ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_RGB565) || \ + ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB1555) || \ + ((MODE_ARGB) == LL_DMA2D_OUTPUT_MODE_ARGB4444)) + +#define IS_LL_DMA2D_GREEN(GREEN) ((GREEN) <= LL_DMA2D_COLOR) +#define IS_LL_DMA2D_RED(RED) ((RED) <= LL_DMA2D_COLOR) +#define IS_LL_DMA2D_BLUE(BLUE) ((BLUE) <= LL_DMA2D_COLOR) +#define IS_LL_DMA2D_ALPHA(ALPHA) ((ALPHA) <= LL_DMA2D_COLOR) + + +#define IS_LL_DMA2D_OFFSET(OFFSET) ((OFFSET) <= LL_DMA2D_OFFSET_MAX) + +#define IS_LL_DMA2D_LINE(LINES) ((LINES) <= LL_DMA2D_NUMBEROFLINES) +#define IS_LL_DMA2D_PIXEL(PIXELS) ((PIXELS) <= LL_DMA2D_NUMBEROFPIXELS) + + + +#define IS_LL_DMA2D_LCMODE(MODE_ARGB) (((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB8888) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_RGB888) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_RGB565) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB1555) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_ARGB4444) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_L8) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_AL44) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_AL88) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_L4) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_A8) || \ + ((MODE_ARGB) == LL_DMA2D_INPUT_MODE_A4)) + +#define IS_LL_DMA2D_CLUTCMODE(CLUTCMODE) (((CLUTCMODE) == LL_DMA2D_CLUT_COLOR_MODE_ARGB8888) || \ + ((CLUTCMODE) == LL_DMA2D_CLUT_COLOR_MODE_RGB888)) + +#define IS_LL_DMA2D_CLUTSIZE(SIZE) ((SIZE) <= LL_DMA2D_CLUTSIZE_MAX) + +#define IS_LL_DMA2D_ALPHAMODE(MODE) (((MODE) == LL_DMA2D_ALPHA_MODE_NO_MODIF) || \ + ((MODE) == LL_DMA2D_ALPHA_MODE_REPLACE) || \ + ((MODE) == LL_DMA2D_ALPHA_MODE_COMBINE)) + + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup DMA2D_LL_Exported_Functions + * @{ + */ + +/** @addtogroup DMA2D_LL_EF_Init_Functions Initialization and De-initialization Functions + * @{ + */ + +/** + * @brief De-initialize DMA2D registers (registers restored to their default values). + * @param DMA2Dx DMA2D Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DMA2D registers are de-initialized + * - ERROR: DMA2D registers are not de-initialized + */ +ErrorStatus LL_DMA2D_DeInit(DMA2D_TypeDef *DMA2Dx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + + if (DMA2Dx == DMA2D) + { + /* Force reset of DMA2D clock */ + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_DMA2D); + + /* Release reset of DMA2D clock */ + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_DMA2D); + } + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Initialize DMA2D registers according to the specified parameters in DMA2D_InitStruct. + * @note DMA2D transfers must be disabled to set initialization bits in configuration registers, + * otherwise ERROR result is returned. + * @param DMA2Dx DMA2D Instance + * @param DMA2D_InitStruct pointer to a LL_DMA2D_InitTypeDef structure + * that contains the configuration information for the specified DMA2D peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: DMA2D registers are initialized according to DMA2D_InitStruct content + * - ERROR: Issue occurred during DMA2D registers initialization + */ +ErrorStatus LL_DMA2D_Init(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_InitTypeDef *DMA2D_InitStruct) +{ + ErrorStatus status = ERROR; + LL_DMA2D_ColorTypeDef dma2d_colorstruct; + uint32_t tmp; + uint32_t tmp1; + uint32_t tmp2; + uint32_t regMask; + uint32_t regValue; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_MODE(DMA2D_InitStruct->Mode)); + assert_param(IS_LL_DMA2D_OCMODE(DMA2D_InitStruct->ColorMode)); + assert_param(IS_LL_DMA2D_LINE(DMA2D_InitStruct->NbrOfLines)); + assert_param(IS_LL_DMA2D_PIXEL(DMA2D_InitStruct->NbrOfPixelsPerLines)); + assert_param(IS_LL_DMA2D_GREEN(DMA2D_InitStruct->OutputGreen)); + assert_param(IS_LL_DMA2D_RED(DMA2D_InitStruct->OutputRed)); + assert_param(IS_LL_DMA2D_BLUE(DMA2D_InitStruct->OutputBlue)); + assert_param(IS_LL_DMA2D_ALPHA(DMA2D_InitStruct->OutputAlpha)); + assert_param(IS_LL_DMA2D_OFFSET(DMA2D_InitStruct->LineOffset)); + + /* DMA2D transfers must be disabled to configure bits in initialization registers */ + tmp = LL_DMA2D_IsTransferOngoing(DMA2Dx); + tmp1 = LL_DMA2D_FGND_IsEnabledCLUTLoad(DMA2Dx); + tmp2 = LL_DMA2D_BGND_IsEnabledCLUTLoad(DMA2Dx); + if ((tmp == 0U) && (tmp1 == 0U) && (tmp2 == 0U)) + { + /* DMA2D CR register configuration -------------------------------------------*/ + LL_DMA2D_SetMode(DMA2Dx, DMA2D_InitStruct->Mode); + + /* DMA2D OPFCCR register configuration ---------------------------------------*/ + regMask = DMA2D_OPFCCR_CM; + regValue = DMA2D_InitStruct->ColorMode; + + + + + MODIFY_REG(DMA2Dx->OPFCCR, regMask, regValue); + + /* DMA2D OOR register configuration ------------------------------------------*/ + LL_DMA2D_SetLineOffset(DMA2Dx, DMA2D_InitStruct->LineOffset); + + /* DMA2D NLR register configuration ------------------------------------------*/ + LL_DMA2D_ConfigSize(DMA2Dx, DMA2D_InitStruct->NbrOfLines, DMA2D_InitStruct->NbrOfPixelsPerLines); + + /* DMA2D OMAR register configuration ------------------------------------------*/ + LL_DMA2D_SetOutputMemAddr(DMA2Dx, DMA2D_InitStruct->OutputMemoryAddress); + + /* DMA2D OCOLR register configuration ------------------------------------------*/ + dma2d_colorstruct.ColorMode = DMA2D_InitStruct->ColorMode; + dma2d_colorstruct.OutputBlue = DMA2D_InitStruct->OutputBlue; + dma2d_colorstruct.OutputGreen = DMA2D_InitStruct->OutputGreen; + dma2d_colorstruct.OutputRed = DMA2D_InitStruct->OutputRed; + dma2d_colorstruct.OutputAlpha = DMA2D_InitStruct->OutputAlpha; + LL_DMA2D_ConfigOutputColor(DMA2Dx, &dma2d_colorstruct); + + status = SUCCESS; + } + /* If DMA2D transfers are not disabled, return ERROR */ + + return (status); +} + +/** + * @brief Set each @ref LL_DMA2D_InitTypeDef field to default value. + * @param DMA2D_InitStruct pointer to a @ref LL_DMA2D_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_DMA2D_StructInit(LL_DMA2D_InitTypeDef *DMA2D_InitStruct) +{ + /* Set DMA2D_InitStruct fields to default values */ + DMA2D_InitStruct->Mode = LL_DMA2D_MODE_M2M; + DMA2D_InitStruct->ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB8888; + DMA2D_InitStruct->NbrOfLines = 0x0U; + DMA2D_InitStruct->NbrOfPixelsPerLines = 0x0U; + DMA2D_InitStruct->LineOffset = 0x0U; + DMA2D_InitStruct->OutputBlue = 0x0U; + DMA2D_InitStruct->OutputGreen = 0x0U; + DMA2D_InitStruct->OutputRed = 0x0U; + DMA2D_InitStruct->OutputAlpha = 0x0U; + DMA2D_InitStruct->OutputMemoryAddress = 0x0U; +} + +/** + * @brief Configure the foreground or background according to the specified parameters + * in the LL_DMA2D_LayerCfgTypeDef structure. + * @param DMA2Dx DMA2D Instance + * @param DMA2D_LayerCfg pointer to a LL_DMA2D_LayerCfgTypeDef structure that contains + * the configuration information for the specified layer. + * @param LayerIdx DMA2D Layer index. + * This parameter can be one of the following values: + * 0(background) / 1(foreground) + * @retval None + */ +void LL_DMA2D_ConfigLayer(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg, uint32_t LayerIdx) +{ + /* Check the parameters */ + assert_param(IS_LL_DMA2D_OFFSET(DMA2D_LayerCfg->LineOffset)); + assert_param(IS_LL_DMA2D_LCMODE(DMA2D_LayerCfg->ColorMode)); + assert_param(IS_LL_DMA2D_CLUTCMODE(DMA2D_LayerCfg->CLUTColorMode)); + assert_param(IS_LL_DMA2D_CLUTSIZE(DMA2D_LayerCfg->CLUTSize)); + assert_param(IS_LL_DMA2D_ALPHAMODE(DMA2D_LayerCfg->AlphaMode)); + assert_param(IS_LL_DMA2D_GREEN(DMA2D_LayerCfg->Green)); + assert_param(IS_LL_DMA2D_RED(DMA2D_LayerCfg->Red)); + assert_param(IS_LL_DMA2D_BLUE(DMA2D_LayerCfg->Blue)); + assert_param(IS_LL_DMA2D_ALPHA(DMA2D_LayerCfg->Alpha)); + + + if (LayerIdx == 0U) + { + /* Configure the background memory address */ + LL_DMA2D_BGND_SetMemAddr(DMA2Dx, DMA2D_LayerCfg->MemoryAddress); + + /* Configure the background line offset */ + LL_DMA2D_BGND_SetLineOffset(DMA2Dx, DMA2D_LayerCfg->LineOffset); + + /* Configure the background Alpha value, Alpha mode, CLUT size, CLUT Color mode and Color mode */ + MODIFY_REG(DMA2Dx->BGPFCCR, \ + (DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_CS | DMA2D_BGPFCCR_CCM | DMA2D_BGPFCCR_CM), \ + ((DMA2D_LayerCfg->Alpha << DMA2D_BGPFCCR_ALPHA_Pos) | DMA2D_LayerCfg->AlphaMode | \ + (DMA2D_LayerCfg->CLUTSize << DMA2D_BGPFCCR_CS_Pos) | DMA2D_LayerCfg->CLUTColorMode | \ + DMA2D_LayerCfg->ColorMode)); + + /* Configure the background color */ + LL_DMA2D_BGND_SetColor(DMA2Dx, DMA2D_LayerCfg->Red, DMA2D_LayerCfg->Green, DMA2D_LayerCfg->Blue); + + /* Configure the background CLUT memory address */ + LL_DMA2D_BGND_SetCLUTMemAddr(DMA2Dx, DMA2D_LayerCfg->CLUTMemoryAddress); + } + else + { + /* Configure the foreground memory address */ + LL_DMA2D_FGND_SetMemAddr(DMA2Dx, DMA2D_LayerCfg->MemoryAddress); + + /* Configure the foreground line offset */ + LL_DMA2D_FGND_SetLineOffset(DMA2Dx, DMA2D_LayerCfg->LineOffset); + + /* Configure the foreground Alpha value, Alpha mode, CLUT size, CLUT Color mode and Color mode */ + MODIFY_REG(DMA2Dx->FGPFCCR, \ + (DMA2D_FGPFCCR_ALPHA | DMA2D_FGPFCCR_AM | DMA2D_FGPFCCR_CS | DMA2D_FGPFCCR_CCM | DMA2D_FGPFCCR_CM), \ + ((DMA2D_LayerCfg->Alpha << DMA2D_FGPFCCR_ALPHA_Pos) | DMA2D_LayerCfg->AlphaMode | \ + (DMA2D_LayerCfg->CLUTSize << DMA2D_FGPFCCR_CS_Pos) | DMA2D_LayerCfg->CLUTColorMode | \ + DMA2D_LayerCfg->ColorMode)); + + /* Configure the foreground color */ + LL_DMA2D_FGND_SetColor(DMA2Dx, DMA2D_LayerCfg->Red, DMA2D_LayerCfg->Green, DMA2D_LayerCfg->Blue); + + /* Configure the foreground CLUT memory address */ + LL_DMA2D_FGND_SetCLUTMemAddr(DMA2Dx, DMA2D_LayerCfg->CLUTMemoryAddress); + } +} + +/** + * @brief Set each @ref LL_DMA2D_LayerCfgTypeDef field to default value. + * @param DMA2D_LayerCfg pointer to a @ref LL_DMA2D_LayerCfgTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_DMA2D_LayerCfgStructInit(LL_DMA2D_LayerCfgTypeDef *DMA2D_LayerCfg) +{ + /* Set DMA2D_LayerCfg fields to default values */ + DMA2D_LayerCfg->MemoryAddress = 0x0U; + DMA2D_LayerCfg->ColorMode = LL_DMA2D_INPUT_MODE_ARGB8888; + DMA2D_LayerCfg->LineOffset = 0x0U; + DMA2D_LayerCfg->CLUTColorMode = LL_DMA2D_CLUT_COLOR_MODE_ARGB8888; + DMA2D_LayerCfg->CLUTSize = 0x0U; + DMA2D_LayerCfg->AlphaMode = LL_DMA2D_ALPHA_MODE_NO_MODIF; + DMA2D_LayerCfg->Alpha = 0x0U; + DMA2D_LayerCfg->Blue = 0x0U; + DMA2D_LayerCfg->Green = 0x0U; + DMA2D_LayerCfg->Red = 0x0U; + DMA2D_LayerCfg->CLUTMemoryAddress = 0x0U; +} + +/** + * @brief Initialize DMA2D output color register according to the specified parameters + * in DMA2D_ColorStruct. + * @param DMA2Dx DMA2D Instance + * @param DMA2D_ColorStruct pointer to a LL_DMA2D_ColorTypeDef structure that contains + * the color configuration information for the specified DMA2D peripheral. + * @retval None + */ +void LL_DMA2D_ConfigOutputColor(DMA2D_TypeDef *DMA2Dx, LL_DMA2D_ColorTypeDef *DMA2D_ColorStruct) +{ + uint32_t outgreen; + uint32_t outred; + uint32_t outalpha; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_OCMODE(DMA2D_ColorStruct->ColorMode)); + assert_param(IS_LL_DMA2D_GREEN(DMA2D_ColorStruct->OutputGreen)); + assert_param(IS_LL_DMA2D_RED(DMA2D_ColorStruct->OutputRed)); + assert_param(IS_LL_DMA2D_BLUE(DMA2D_ColorStruct->OutputBlue)); + assert_param(IS_LL_DMA2D_ALPHA(DMA2D_ColorStruct->OutputAlpha)); + + /* DMA2D OCOLR register configuration ------------------------------------------*/ + if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888) + { + outgreen = DMA2D_ColorStruct->OutputGreen << 8U; + outred = DMA2D_ColorStruct->OutputRed << 16U; + outalpha = DMA2D_ColorStruct->OutputAlpha << 24U; + } + else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) + { + outgreen = DMA2D_ColorStruct->OutputGreen << 8U; + outred = DMA2D_ColorStruct->OutputRed << 16U; + outalpha = 0x00000000U; + } + else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565) + { + outgreen = DMA2D_ColorStruct->OutputGreen << 5U; + outred = DMA2D_ColorStruct->OutputRed << 11U; + outalpha = 0x00000000U; + } + else if (DMA2D_ColorStruct->ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555) + { + outgreen = DMA2D_ColorStruct->OutputGreen << 5U; + outred = DMA2D_ColorStruct->OutputRed << 10U; + outalpha = DMA2D_ColorStruct->OutputAlpha << 15U; + } + else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */ + { + outgreen = DMA2D_ColorStruct->OutputGreen << 4U; + outred = DMA2D_ColorStruct->OutputRed << 8U; + outalpha = DMA2D_ColorStruct->OutputAlpha << 12U; + } + LL_DMA2D_SetOutputColor(DMA2Dx, (outgreen | outred | DMA2D_ColorStruct->OutputBlue | outalpha)); +} + +/** + * @brief Return DMA2D output Blue color. + * @param DMA2Dx DMA2D Instance. + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + * @retval Output Blue color value between Min_Data=0 and Max_Data=0xFF + */ +uint32_t LL_DMA2D_GetOutputBlueColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + uint32_t color; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_OCMODE(ColorMode)); + + /* DMA2D OCOLR register reading ------------------------------------------*/ + if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFFU)); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFFU)); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x1FU)); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x1FU)); + } + else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */ + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFU)); + } + + return color; +} + +/** + * @brief Return DMA2D output Green color. + * @param DMA2Dx DMA2D Instance. + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + * @retval Output Green color value between Min_Data=0 and Max_Data=0xFF + */ +uint32_t LL_DMA2D_GetOutputGreenColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + uint32_t color; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_OCMODE(ColorMode)); + + /* DMA2D OCOLR register reading ------------------------------------------*/ + if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF00U) >> 8U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF00U) >> 8U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x7E0U) >> 5U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x3E0U) >> 5U); + } + else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */ + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF0U) >> 4U); + } + + return color; +} + +/** + * @brief Return DMA2D output Red color. + * @param DMA2Dx DMA2D Instance. + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + * @retval Output Red color value between Min_Data=0 and Max_Data=0xFF + */ +uint32_t LL_DMA2D_GetOutputRedColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + uint32_t color; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_OCMODE(ColorMode)); + + /* DMA2D OCOLR register reading ------------------------------------------*/ + if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF0000U) >> 16U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF0000U) >> 16U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF800U) >> 11U); + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x7C00U) >> 10U); + } + else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */ + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF00U) >> 8U); + } + + return color; +} + +/** + * @brief Return DMA2D output Alpha color. + * @param DMA2Dx DMA2D Instance. + * @param ColorMode This parameter can be one of the following values: + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB8888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB888 + * @arg @ref LL_DMA2D_OUTPUT_MODE_RGB565 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB1555 + * @arg @ref LL_DMA2D_OUTPUT_MODE_ARGB4444 + * @retval Output Alpha color value between Min_Data=0 and Max_Data=0xFF + */ +uint32_t LL_DMA2D_GetOutputAlphaColor(DMA2D_TypeDef *DMA2Dx, uint32_t ColorMode) +{ + uint32_t color; + + /* Check the parameters */ + assert_param(IS_DMA2D_ALL_INSTANCE(DMA2Dx)); + assert_param(IS_LL_DMA2D_OCMODE(ColorMode)); + + /* DMA2D OCOLR register reading ------------------------------------------*/ + if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB8888) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xFF000000U) >> 24U); + } + else if ((ColorMode == LL_DMA2D_OUTPUT_MODE_RGB888) || (ColorMode == LL_DMA2D_OUTPUT_MODE_RGB565)) + { + color = 0x0U; + } + else if (ColorMode == LL_DMA2D_OUTPUT_MODE_ARGB1555) + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0x8000U) >> 15U); + } + else /* ColorMode = LL_DMA2D_OUTPUT_MODE_ARGB4444 */ + { + color = (uint32_t)(READ_BIT(DMA2Dx->OCOLR, 0xF000U) >> 12U); + } + + return color; +} + +/** + * @brief Configure DMA2D transfer size. + * @param DMA2Dx DMA2D Instance + * @param NbrOfLines Value between Min_Data=0 and Max_Data=0xFFFF + * @param NbrOfPixelsPerLines Value between Min_Data=0 and Max_Data=0x3FFF + * @retval None + */ +void LL_DMA2D_ConfigSize(DMA2D_TypeDef *DMA2Dx, uint32_t NbrOfLines, uint32_t NbrOfPixelsPerLines) +{ + MODIFY_REG(DMA2Dx->NLR, (DMA2D_NLR_PL | DMA2D_NLR_NL), \ + ((NbrOfPixelsPerLines << DMA2D_NLR_PL_Pos) | NbrOfLines)); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (DMA2D) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c new file mode 100644 index 0000000..ce2f7b0 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c @@ -0,0 +1,212 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_exti.c + * @author MCD Application Team + * @brief EXTI LL module driver. + ****************************************************************************** + * @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.Clause + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_exti.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (EXTI) + +/** @defgroup EXTI_LL EXTI + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup EXTI_LL_Private_Macros + * @{ + */ + +#define IS_LL_EXTI_LINE_0_31(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_0_31) == 0x00000000U) + +#define IS_LL_EXTI_MODE(__VALUE__) (((__VALUE__) == LL_EXTI_MODE_IT) \ + || ((__VALUE__) == LL_EXTI_MODE_EVENT) \ + || ((__VALUE__) == LL_EXTI_MODE_IT_EVENT)) + + +#define IS_LL_EXTI_TRIGGER(__VALUE__) (((__VALUE__) == LL_EXTI_TRIGGER_NONE) \ + || ((__VALUE__) == LL_EXTI_TRIGGER_RISING) \ + || ((__VALUE__) == LL_EXTI_TRIGGER_FALLING) \ + || ((__VALUE__) == LL_EXTI_TRIGGER_RISING_FALLING)) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup EXTI_LL_Exported_Functions + * @{ + */ + +/** @addtogroup EXTI_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the EXTI registers to their default reset values. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: EXTI registers are de-initialized + * - ERROR: not applicable + */ +uint32_t LL_EXTI_DeInit(void) +{ + /* Interrupt mask register set to default reset values */ + LL_EXTI_WriteReg(IMR, 0x00000000U); + /* Event mask register set to default reset values */ + LL_EXTI_WriteReg(EMR, 0x00000000U); + /* Rising Trigger selection register set to default reset values */ + LL_EXTI_WriteReg(RTSR, 0x00000000U); + /* Falling Trigger selection register set to default reset values */ + LL_EXTI_WriteReg(FTSR, 0x00000000U); + /* Software interrupt event register set to default reset values */ + LL_EXTI_WriteReg(SWIER, 0x00000000U); + /* Pending register set to default reset values */ + LL_EXTI_WriteReg(PR, 0x00FFFFFFU); + + return SUCCESS; +} + +/** + * @brief Initialize the EXTI registers according to the specified parameters in EXTI_InitStruct. + * @param EXTI_InitStruct pointer to a @ref LL_EXTI_InitTypeDef structure. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: EXTI registers are initialized + * - ERROR: not applicable + */ +uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct) +{ + ErrorStatus status = SUCCESS; + /* Check the parameters */ + assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31)); + assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->LineCommand)); + assert_param(IS_LL_EXTI_MODE(EXTI_InitStruct->Mode)); + + /* ENABLE LineCommand */ + if (EXTI_InitStruct->LineCommand != DISABLE) + { + assert_param(IS_LL_EXTI_TRIGGER(EXTI_InitStruct->Trigger)); + + /* Configure EXTI Lines in range from 0 to 31 */ + if (EXTI_InitStruct->Line_0_31 != LL_EXTI_LINE_NONE) + { + switch (EXTI_InitStruct->Mode) + { + case LL_EXTI_MODE_IT: + /* First Disable Event on provided Lines */ + LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31); + /* Then Enable IT on provided Lines */ + LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31); + break; + case LL_EXTI_MODE_EVENT: + /* First Disable IT on provided Lines */ + LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31); + /* Then Enable Event on provided Lines */ + LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31); + break; + case LL_EXTI_MODE_IT_EVENT: + /* Directly Enable IT & Event on provided Lines */ + LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31); + LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31); + break; + default: + status = ERROR; + break; + } + if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE) + { + switch (EXTI_InitStruct->Trigger) + { + case LL_EXTI_TRIGGER_RISING: + /* First Disable Falling Trigger on provided Lines */ + LL_EXTI_DisableFallingTrig_0_31(EXTI_InitStruct->Line_0_31); + /* Then Enable Rising Trigger on provided Lines */ + LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31); + break; + case LL_EXTI_TRIGGER_FALLING: + /* First Disable Rising Trigger on provided Lines */ + LL_EXTI_DisableRisingTrig_0_31(EXTI_InitStruct->Line_0_31); + /* Then Enable Falling Trigger on provided Lines */ + LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31); + break; + case LL_EXTI_TRIGGER_RISING_FALLING: + LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31); + LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31); + break; + default: + status = ERROR; + break; + } + } + } + } + /* DISABLE LineCommand */ + else + { + /* De-configure EXTI Lines in range from 0 to 31 */ + LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31); + LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31); + } + return status; +} + +/** + * @brief Set each @ref LL_EXTI_InitTypeDef field to default value. + * @param EXTI_InitStruct Pointer to a @ref LL_EXTI_InitTypeDef structure. + * @retval None + */ +void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct) +{ + EXTI_InitStruct->Line_0_31 = LL_EXTI_LINE_NONE; + EXTI_InitStruct->LineCommand = DISABLE; + EXTI_InitStruct->Mode = LL_EXTI_MODE_IT; + EXTI_InitStruct->Trigger = LL_EXTI_TRIGGER_FALLING; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (EXTI) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c new file mode 100644 index 0000000..1bdf9de --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmc.c @@ -0,0 +1,1498 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fmc.c + * @author MCD Application Team + * @brief FMC Low Layer HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the Flexible Memory Controller (FMC) peripheral memories: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + Peripheral State 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 + ============================================================================== + ##### FMC peripheral features ##### + ============================================================================== + [..] The Flexible memory controller (FMC) includes following memory controllers: + (+) The NOR/PSRAM memory controller + (+) The NAND/PC Card memory controller + (+) The Synchronous DRAM (SDRAM) controller + + [..] The FMC functional block makes the interface with synchronous and asynchronous static + memories, SDRAM memories, and 16-bit PC memory cards. Its main purposes are: + (+) to translate AHB transactions into the appropriate external device protocol + (+) to meet the access time requirements of the external memory devices + + [..] All external memories share the addresses, data and control signals with the controller. + Each external device is accessed by means of a unique Chip Select. The FMC performs + only one access at a time to an external device. + The main features of the FMC controller are the following: + (+) Interface with static-memory mapped devices including: + (++) Static random access memory (SRAM) + (++) Read-only memory (ROM) + (++) NOR Flash memory/OneNAND Flash memory + (++) PSRAM (4 memory banks) + (++) 16-bit PC Card compatible devices + (++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of + data + (+) Interface with synchronous DRAM (SDRAM) memories + (+) Independent Chip Select control for each memory bank + (+) Independent configuration for each memory bank + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_SRAM_MODULE_ENABLED) || (defined(HAL_NAND_MODULE_ENABLED)) || defined(HAL_PCCARD_MODULE_ENABLED) || defined(HAL_SDRAM_MODULE_ENABLED) + +/** @defgroup FMC_LL FMC Low Layer + * @brief FMC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup FMC_LL_Private_Constants FMC Low Layer Private Constants + * @{ + */ + +/* ----------------------- FMC registers bit mask --------------------------- */ + +#if defined(FMC_Bank1) +/* --- BCR Register ---*/ +/* BCR register clear mask */ + +/* --- BTR Register ---*/ +/* BTR register clear mask */ +#define BTR_CLEAR_MASK ((uint32_t)(FMC_BTR1_ADDSET | FMC_BTR1_ADDHLD |\ + FMC_BTR1_DATAST | FMC_BTR1_BUSTURN |\ + FMC_BTR1_CLKDIV | FMC_BTR1_DATLAT |\ + FMC_BTR1_ACCMOD)) + +/* --- BWTR Register ---*/ +/* BWTR register clear mask */ +#define BWTR_CLEAR_MASK ((uint32_t)(FMC_BWTR1_ADDSET | FMC_BWTR1_ADDHLD |\ + FMC_BWTR1_DATAST | FMC_BWTR1_BUSTURN |\ + FMC_BWTR1_ACCMOD)) +#endif /* FMC_Bank1 */ +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + +#if defined (FMC_PCR_PWAITEN) +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR_CLEAR_MASK ((uint32_t)(FMC_PCR_PWAITEN | FMC_PCR_PBKEN | \ + FMC_PCR_PTYP | FMC_PCR_PWID | \ + FMC_PCR_ECCEN | FMC_PCR_TCLR | \ + FMC_PCR_TAR | FMC_PCR_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM_CLEAR_MASK ((uint32_t)(FMC_PMEM_MEMSET2 | FMC_PMEM_MEMWAIT2 |\ + FMC_PMEM_MEMHOLD2 | FMC_PMEM_MEMHIZ2)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT_CLEAR_MASK ((uint32_t)(FMC_PATT_ATTSET2 | FMC_PATT_ATTWAIT2 |\ + FMC_PATT_ATTHOLD2 | FMC_PATT_ATTHIZ2)) +#else +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR_CLEAR_MASK ((uint32_t)(FMC_PCR2_PWAITEN | FMC_PCR2_PBKEN | \ + FMC_PCR2_PTYP | FMC_PCR2_PWID | \ + FMC_PCR2_ECCEN | FMC_PCR2_TCLR | \ + FMC_PCR2_TAR | FMC_PCR2_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM_CLEAR_MASK ((uint32_t)(FMC_PMEM2_MEMSET2 | FMC_PMEM2_MEMWAIT2 |\ + FMC_PMEM2_MEMHOLD2 | FMC_PMEM2_MEMHIZ2)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT_CLEAR_MASK ((uint32_t)(FMC_PATT2_ATTSET2 | FMC_PATT2_ATTWAIT2 |\ + FMC_PATT2_ATTHOLD2 | FMC_PATT2_ATTHIZ2)) + +#endif /* FMC_PCR_PWAITEN */ +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ +#if defined(FMC_Bank4) +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR4_CLEAR_MASK ((uint32_t)(FMC_PCR4_PWAITEN | FMC_PCR4_PBKEN | \ + FMC_PCR4_PTYP | FMC_PCR4_PWID | \ + FMC_PCR4_ECCEN | FMC_PCR4_TCLR | \ + FMC_PCR4_TAR | FMC_PCR4_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM4_CLEAR_MASK ((uint32_t)(FMC_PMEM4_MEMSET4 | FMC_PMEM4_MEMWAIT4 |\ + FMC_PMEM4_MEMHOLD4 | FMC_PMEM4_MEMHIZ4)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT4_CLEAR_MASK ((uint32_t)(FMC_PATT4_ATTSET4 | FMC_PATT4_ATTWAIT4 |\ + FMC_PATT4_ATTHOLD4 | FMC_PATT4_ATTHIZ4)) + +/* --- PIO4 Register ---*/ +/* PIO4 register clear mask */ +#define PIO4_CLEAR_MASK ((uint32_t)(FMC_PIO4_IOSET4 | FMC_PIO4_IOWAIT4 | \ + FMC_PIO4_IOHOLD4 | FMC_PIO4_IOHIZ4)) + +#endif /* FMC_Bank4 */ +#if defined(FMC_Bank5_6) + +/* --- SDCR Register ---*/ +/* SDCR register clear mask */ +#define SDCR_CLEAR_MASK ((uint32_t)(FMC_SDCR1_NC | FMC_SDCR1_NR | \ + FMC_SDCR1_MWID | FMC_SDCR1_NB | \ + FMC_SDCR1_CAS | FMC_SDCR1_WP | \ + FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | \ + FMC_SDCR1_RPIPE)) + +/* --- SDTR Register ---*/ +/* SDTR register clear mask */ +#define SDTR_CLEAR_MASK ((uint32_t)(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | \ + FMC_SDTR1_TRAS | FMC_SDTR1_TRC | \ + FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ + FMC_SDTR1_TRCD)) +#endif /* FMC_Bank5_6 */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup FMC_LL_Exported_Functions FMC Low Layer Exported Functions + * @{ + */ + +#if defined(FMC_Bank1) + +/** @defgroup FMC_LL_Exported_Functions_NORSRAM FMC Low Layer NOR SRAM Exported Functions + * @brief NORSRAM Controller functions + * + @verbatim + ============================================================================== + ##### How to use NORSRAM device driver ##### + ============================================================================== + + [..] + This driver contains a set of APIs to interface with the FMC NORSRAM banks in order + to run the NORSRAM external devices. + + (+) FMC NORSRAM bank reset using the function FMC_NORSRAM_DeInit() + (+) FMC NORSRAM bank control configuration using the function FMC_NORSRAM_Init() + (+) FMC NORSRAM bank timing configuration using the function FMC_NORSRAM_Timing_Init() + (+) FMC NORSRAM bank extended timing configuration using the function + FMC_NORSRAM_Extended_Timing_Init() + (+) FMC NORSRAM bank enable/disable write operation using the functions + FMC_NORSRAM_WriteOperation_Enable()/FMC_NORSRAM_WriteOperation_Disable() + +@endverbatim + * @{ + */ + +/** @defgroup FMC_LL_NORSRAM_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FMC NORSRAM interface + (+) De-initialize the FMC NORSRAM interface + (+) Configure the FMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the FMC_NORSRAM device according to the specified + * control parameters in the FMC_NORSRAM_InitTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Init Pointer to NORSRAM Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_Init(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_InitTypeDef *Init) +{ + uint32_t flashaccess; + uint32_t btcr_reg; + uint32_t mask; + + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FMC_NORSRAM_BANK(Init->NSBank)); + assert_param(IS_FMC_MUX(Init->DataAddressMux)); + assert_param(IS_FMC_MEMORY(Init->MemoryType)); + assert_param(IS_FMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth)); + assert_param(IS_FMC_BURSTMODE(Init->BurstAccessMode)); + assert_param(IS_FMC_WAIT_POLARITY(Init->WaitSignalPolarity)); +#if defined(FMC_BCR1_WRAPMOD) + assert_param(IS_FMC_WRAP_MODE(Init->WrapMode)); +#endif /* FMC_BCR1_WRAPMOD */ + assert_param(IS_FMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive)); + assert_param(IS_FMC_WRITE_OPERATION(Init->WriteOperation)); + assert_param(IS_FMC_WAITE_SIGNAL(Init->WaitSignal)); + assert_param(IS_FMC_EXTENDED_MODE(Init->ExtendedMode)); + assert_param(IS_FMC_ASYNWAIT(Init->AsynchronousWait)); + assert_param(IS_FMC_WRITE_BURST(Init->WriteBurst)); +#if defined(FMC_BCR1_CCLKEN) + assert_param(IS_FMC_CONTINOUS_CLOCK(Init->ContinuousClock)); +#endif +#if defined(FMC_BCR1_WFDIS) + assert_param(IS_FMC_WRITE_FIFO(Init->WriteFifo)); +#endif /* FMC_BCR1_WFDIS */ + assert_param(IS_FMC_PAGESIZE(Init->PageSize)); + + /* Disable NORSRAM Device */ + __FMC_NORSRAM_DISABLE(Device, Init->NSBank); + + /* Set NORSRAM device control parameters */ + if (Init->MemoryType == FMC_MEMORY_TYPE_NOR) + { + flashaccess = FMC_NORSRAM_FLASH_ACCESS_ENABLE; + } + else + { + flashaccess = FMC_NORSRAM_FLASH_ACCESS_DISABLE; + } + + btcr_reg = (flashaccess | \ + Init->DataAddressMux | \ + Init->MemoryType | \ + Init->MemoryDataWidth | \ + Init->BurstAccessMode | \ + Init->WaitSignalPolarity | \ + Init->WaitSignalActive | \ + Init->WriteOperation | \ + Init->WaitSignal | \ + Init->ExtendedMode | \ + Init->AsynchronousWait | \ + Init->WriteBurst); + +#if defined(FMC_BCR1_WRAPMOD) + btcr_reg |= Init->WrapMode; +#endif /* FMC_BCR1_WRAPMOD */ +#if defined(FMC_BCR1_CCLKEN) + btcr_reg |= Init->ContinuousClock; +#endif /* FMC_BCR1_CCLKEN */ +#if defined(FMC_BCR1_WFDIS) + btcr_reg |= Init->WriteFifo; +#endif /* FMC_BCR1_WFDIS */ + btcr_reg |= Init->PageSize; + + mask = (FMC_BCR1_MBKEN | + FMC_BCR1_MUXEN | + FMC_BCR1_MTYP | + FMC_BCR1_MWID | + FMC_BCR1_FACCEN | + FMC_BCR1_BURSTEN | + FMC_BCR1_WAITPOL | + FMC_BCR1_WAITCFG | + FMC_BCR1_WREN | + FMC_BCR1_WAITEN | + FMC_BCR1_EXTMOD | + FMC_BCR1_ASYNCWAIT | + FMC_BCR1_CBURSTRW); + +#if defined(FMC_BCR1_WRAPMOD) + mask |= FMC_BCR1_WRAPMOD; +#endif /* FMC_BCR1_WRAPMOD */ +#if defined(FMC_BCR1_CCLKEN) + mask |= FMC_BCR1_CCLKEN; +#endif +#if defined(FMC_BCR1_WFDIS) + mask |= FMC_BCR1_WFDIS; +#endif /* FMC_BCR1_WFDIS */ + mask |= FMC_BCR1_CPSIZE; + + MODIFY_REG(Device->BTCR[Init->NSBank], mask, btcr_reg); + +#if defined(FMC_BCR1_CCLKEN) + /* Configure synchronous mode when Continuous clock is enabled for bank2..4 */ + if ((Init->ContinuousClock == FMC_CONTINUOUS_CLOCK_SYNC_ASYNC) && (Init->NSBank != FMC_NORSRAM_BANK1)) + { + MODIFY_REG(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN, Init->ContinuousClock); + } +#endif +#if defined(FMC_BCR1_WFDIS) + + if (Init->NSBank != FMC_NORSRAM_BANK1) + { + /* Configure Write FIFO mode when Write Fifo is enabled for bank2..4 */ + SET_BIT(Device->BTCR[FMC_NORSRAM_BANK1], (uint32_t)(Init->WriteFifo)); + } +#endif /* FMC_BCR1_WFDIS */ + + return HAL_OK; +} + +/** + * @brief DeInitialize the FMC_NORSRAM peripheral + * @param Device Pointer to NORSRAM device instance + * @param ExDevice Pointer to NORSRAM extended mode device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_DeInit(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(ExDevice)); + assert_param(IS_FMC_NORSRAM_BANK(Bank)); + + /* Disable the FMC_NORSRAM device */ + __FMC_NORSRAM_DISABLE(Device, Bank); + + /* De-initialize the FMC_NORSRAM device */ + /* FMC_NORSRAM_BANK1 */ + if (Bank == FMC_NORSRAM_BANK1) + { + Device->BTCR[Bank] = 0x000030DBU; + } + /* FMC_NORSRAM_BANK2, FMC_NORSRAM_BANK3 or FMC_NORSRAM_BANK4 */ + else + { + Device->BTCR[Bank] = 0x000030D2U; + } + + Device->BTCR[Bank + 1U] = 0x0FFFFFFFU; + ExDevice->BWTR[Bank] = 0x0FFFFFFFU; + + return HAL_OK; +} + +/** + * @brief Initialize the FMC_NORSRAM Timing according to the specified + * parameters in the FMC_NORSRAM_TimingTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Timing Pointer to NORSRAM Timing structure + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_Timing_Init(FMC_NORSRAM_TypeDef *Device, + FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank) +{ +#if defined(FMC_BCR1_CCLKEN) + uint32_t tmpr; +#endif + + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime)); + assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime)); + assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime)); + assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration)); + assert_param(IS_FMC_CLK_DIV(Timing->CLKDivision)); + assert_param(IS_FMC_DATA_LATENCY(Timing->DataLatency)); + assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode)); + assert_param(IS_FMC_NORSRAM_BANK(Bank)); + + /* Set FMC_NORSRAM device timing parameters */ + MODIFY_REG(Device->BTCR[Bank + 1U], BTR_CLEAR_MASK, (Timing->AddressSetupTime | + ((Timing->AddressHoldTime) << FMC_BTR1_ADDHLD_Pos) | + ((Timing->DataSetupTime) << FMC_BTR1_DATAST_Pos) | + ((Timing->BusTurnAroundDuration) << FMC_BTR1_BUSTURN_Pos) | + (((Timing->CLKDivision) - 1U) << FMC_BTR1_CLKDIV_Pos) | + (((Timing->DataLatency) - 2U) << FMC_BTR1_DATLAT_Pos) | + (Timing->AccessMode))); + +#if defined(FMC_BCR1_CCLKEN) + /* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */ + if (HAL_IS_BIT_SET(Device->BTCR[FMC_NORSRAM_BANK1], FMC_BCR1_CCLKEN)) + { + tmpr = (uint32_t)(Device->BTCR[FMC_NORSRAM_BANK1 + 1U] & ~((0x0FU) << FMC_BTR1_CLKDIV_Pos)); + tmpr |= (uint32_t)(((Timing->CLKDivision) - 1U) << FMC_BTR1_CLKDIV_Pos); + MODIFY_REG(Device->BTCR[FMC_NORSRAM_BANK1 + 1U], FMC_BTR1_CLKDIV, tmpr); + } + +#endif + return HAL_OK; +} + +/** + * @brief Initialize the FMC_NORSRAM Extended mode Timing according to the specified + * parameters in the FMC_NORSRAM_TimingTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Timing Pointer to NORSRAM Timing structure + * @param Bank NORSRAM bank number + * @param ExtendedMode FMC Extended Mode + * This parameter can be one of the following values: + * @arg FMC_EXTENDED_MODE_DISABLE + * @arg FMC_EXTENDED_MODE_ENABLE + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_Extended_Timing_Init(FMC_NORSRAM_EXTENDED_TypeDef *Device, + FMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, + uint32_t ExtendedMode) +{ + /* Check the parameters */ + assert_param(IS_FMC_EXTENDED_MODE(ExtendedMode)); + + /* Set NORSRAM device timing register for write configuration, if extended mode is used */ + if (ExtendedMode == FMC_EXTENDED_MODE_ENABLE) + { + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_EXTENDED_DEVICE(Device)); + assert_param(IS_FMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime)); + assert_param(IS_FMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime)); + assert_param(IS_FMC_DATASETUP_TIME(Timing->DataSetupTime)); + assert_param(IS_FMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration)); + assert_param(IS_FMC_ACCESS_MODE(Timing->AccessMode)); + assert_param(IS_FMC_NORSRAM_BANK(Bank)); + + /* Set NORSRAM device timing register for write configuration, if extended mode is used */ + MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime | + ((Timing->AddressHoldTime) << FMC_BWTR1_ADDHLD_Pos) | + ((Timing->DataSetupTime) << FMC_BWTR1_DATAST_Pos) | + Timing->AccessMode | + ((Timing->BusTurnAroundDuration) << FMC_BWTR1_BUSTURN_Pos))); + } + else + { + Device->BWTR[Bank] = 0x0FFFFFFFU; + } + + return HAL_OK; +} +/** + * @} + */ + +/** @addtogroup FMC_LL_NORSRAM_Private_Functions_Group2 + * @brief management functions + * +@verbatim + ============================================================================== + ##### FMC_NORSRAM Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the FMC NORSRAM interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically FMC_NORSRAM write operation. + * @param Device Pointer to NORSRAM device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Enable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FMC_NORSRAM_BANK(Bank)); + + /* Enable write operation */ + SET_BIT(Device->BTCR[Bank], FMC_WRITE_OPERATION_ENABLE); + + return HAL_OK; +} + +/** + * @brief Disables dynamically FMC_NORSRAM write operation. + * @param Device Pointer to NORSRAM device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NORSRAM_WriteOperation_Disable(FMC_NORSRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FMC_NORSRAM_BANK(Bank)); + + /* Disable write operation */ + CLEAR_BIT(Device->BTCR[Bank], FMC_WRITE_OPERATION_ENABLE); + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ +#endif /* FMC_Bank1 */ + +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + +/** @defgroup FMC_LL_Exported_Functions_NAND FMC Low Layer NAND Exported Functions + * @brief NAND Controller functions + * + @verbatim + ============================================================================== + ##### How to use NAND device driver ##### + ============================================================================== + [..] + This driver contains a set of APIs to interface with the FMC NAND banks in order + to run the NAND external devices. + + (+) FMC NAND bank reset using the function FMC_NAND_DeInit() + (+) FMC NAND bank control configuration using the function FMC_NAND_Init() + (+) FMC NAND bank common space timing configuration using the function + FMC_NAND_CommonSpace_Timing_Init() + (+) FMC NAND bank attribute space timing configuration using the function + FMC_NAND_AttributeSpace_Timing_Init() + (+) FMC NAND bank enable/disable ECC correction feature using the functions + FMC_NAND_ECC_Enable()/FMC_NAND_ECC_Disable() + (+) FMC NAND bank get ECC correction code using the function FMC_NAND_GetECC() + +@endverbatim + * @{ + */ + +/** @defgroup FMC_LL_NAND_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FMC NAND interface + (+) De-initialize the FMC NAND interface + (+) Configure the FMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FMC_NAND device according to the specified + * control parameters in the FMC_NAND_HandleTypeDef + * @param Device Pointer to NAND device instance + * @param Init Pointer to NAND Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_Init(FMC_NAND_TypeDef *Device, FMC_NAND_InitTypeDef *Init) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_NAND_BANK(Init->NandBank)); + assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature)); + assert_param(IS_FMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth)); + assert_param(IS_FMC_ECC_STATE(Init->EccComputation)); + assert_param(IS_FMC_ECCPAGE_SIZE(Init->ECCPageSize)); + assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime)); + assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime)); + +#if defined(FMC_Bank2_3) + /* Set NAND device control parameters */ + if (Init->NandBank == FMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PCR2, PCR_CLEAR_MASK, (Init->Waitfeature | + FMC_PCR_MEMORY_TYPE_NAND | + Init->MemoryDataWidth | + Init->EccComputation | + Init->ECCPageSize | + ((Init->TCLRSetupTime) << FMC_PCR2_TCLR_Pos) | + ((Init->TARSetupTime) << FMC_PCR2_TAR_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PCR3, PCR_CLEAR_MASK, (Init->Waitfeature | + FMC_PCR_MEMORY_TYPE_NAND | + Init->MemoryDataWidth | + Init->EccComputation | + Init->ECCPageSize | + ((Init->TCLRSetupTime) << FMC_PCR2_TCLR_Pos) | + ((Init->TARSetupTime) << FMC_PCR2_TAR_Pos))); + } +#else + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PCR, PCR_CLEAR_MASK, (Init->Waitfeature | + FMC_PCR_MEMORY_TYPE_NAND | + Init->MemoryDataWidth | + Init->EccComputation | + Init->ECCPageSize | + ((Init->TCLRSetupTime) << FMC_PCR_TCLR_Pos) | + ((Init->TARSetupTime) << FMC_PCR_TAR_Pos))); +#endif + + return HAL_OK; +} + +/** + * @brief Initializes the FMC_NAND Common space Timing according to the specified + * parameters in the FMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to NAND device instance + * @param Timing Pointer to NAND timing structure + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_CommonSpace_Timing_Init(FMC_NAND_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime)); + assert_param(IS_FMC_NAND_BANK(Bank)); + +#if defined(FMC_Bank2_3) + /* Set FMC_NAND device timing parameters */ + if (Bank == FMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PMEM2, PMEM_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PMEM2_MEMWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PMEM2_MEMHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PMEM2_MEMHIZ2_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PMEM3, PMEM_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PMEM2_MEMWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PMEM2_MEMHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PMEM2_MEMHIZ2_Pos))); + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PMEM, PMEM_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PMEM_MEMWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PMEM_MEMHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PMEM_MEMHIZ2_Pos))); +#endif + + return HAL_OK; +} + +/** + * @brief Initializes the FMC_NAND Attribute space Timing according to the specified + * parameters in the FMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to NAND device instance + * @param Timing Pointer to NAND timing structure + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_AttributeSpace_Timing_Init(FMC_NAND_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime)); + assert_param(IS_FMC_NAND_BANK(Bank)); + +#if defined(FMC_Bank2_3) + /* Set FMC_NAND device timing parameters */ + if (Bank == FMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PATT2, PATT_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PATT2_ATTWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PATT2_ATTHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PATT2_ATTHIZ2_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PATT3, PATT_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PATT2_ATTWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PATT2_ATTHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PATT2_ATTHIZ2_Pos))); + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PATT, PATT_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PATT_ATTWAIT2_Pos) | + ((Timing->HoldSetupTime) << FMC_PATT_ATTHOLD2_Pos) | + ((Timing->HiZSetupTime) << FMC_PATT_ATTHIZ2_Pos))); +#endif + + return HAL_OK; +} + +/** + * @brief DeInitializes the FMC_NAND device + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_DeInit(FMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_NAND_BANK(Bank)); + + /* Disable the NAND Bank */ + __FMC_NAND_DISABLE(Device, Bank); + + /* De-initialize the NAND Bank */ +#if defined(FMC_Bank2_3) + if (Bank == FMC_NAND_BANK2) + { + /* Set the FMC_NAND_BANK2 registers to their reset values */ + WRITE_REG(Device->PCR2, 0x00000018U); + WRITE_REG(Device->SR2, 0x00000040U); + WRITE_REG(Device->PMEM2, 0xFCFCFCFCU); + WRITE_REG(Device->PATT2, 0xFCFCFCFCU); + } + /* FMC_Bank3_NAND */ + else + { + /* Set the FMC_NAND_BANK3 registers to their reset values */ + WRITE_REG(Device->PCR3, 0x00000018U); + WRITE_REG(Device->SR3, 0x00000040U); + WRITE_REG(Device->PMEM3, 0xFCFCFCFCU); + WRITE_REG(Device->PATT3, 0xFCFCFCFCU); + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + /* Set the FMC_NAND_BANK3 registers to their reset values */ + WRITE_REG(Device->PCR, 0x00000018U); + WRITE_REG(Device->SR, 0x00000040U); + WRITE_REG(Device->PMEM, 0xFCFCFCFCU); + WRITE_REG(Device->PATT, 0xFCFCFCFCU); +#endif + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup HAL_FMC_NAND_Group2 Peripheral Control functions + * @brief management functions + * +@verbatim + ============================================================================== + ##### FMC_NAND Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the FMC NAND interface. + +@endverbatim + * @{ + */ + + +/** + * @brief Enables dynamically FMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_ECC_Enable(FMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_NAND_BANK(Bank)); + + /* Enable ECC feature */ +#if defined(FMC_Bank2_3) + if (Bank == FMC_NAND_BANK2) + { + SET_BIT(Device->PCR2, FMC_PCR2_ECCEN); + } + else + { + SET_BIT(Device->PCR3, FMC_PCR2_ECCEN); + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + SET_BIT(Device->PCR, FMC_PCR_ECCEN); +#endif + + return HAL_OK; +} + + +/** + * @brief Disables dynamically FMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_ECC_Disable(FMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_NAND_BANK(Bank)); + + /* Disable ECC feature */ +#if defined(FMC_Bank2_3) + if (Bank == FMC_NAND_BANK2) + { + CLEAR_BIT(Device->PCR2, FMC_PCR2_ECCEN); + } + else + { + CLEAR_BIT(Device->PCR3, FMC_PCR2_ECCEN); + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + CLEAR_BIT(Device->PCR, FMC_PCR_ECCEN); +#endif + + return HAL_OK; +} + +/** + * @brief Disables dynamically FMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param ECCval Pointer to ECC value + * @param Bank NAND bank number + * @param Timeout Timeout wait value + * @retval HAL status + */ +HAL_StatusTypeDef FMC_NAND_GetECC(FMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, + uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check the parameters */ + assert_param(IS_FMC_NAND_DEVICE(Device)); + assert_param(IS_FMC_NAND_BANK(Bank)); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until FIFO is empty */ + while (__FMC_NAND_GET_FLAG(Device, Bank, FMC_FLAG_FEMPT) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_TIMEOUT; + } + } + } + +#if defined(FMC_Bank2_3) + if (Bank == FMC_NAND_BANK2) + { + /* Get the ECCR2 register value */ + *ECCval = (uint32_t)Device->ECCR2; + } + else + { + /* Get the ECCR3 register value */ + *ECCval = (uint32_t)Device->ECCR3; + } +#else + /* Prevent unused argument(s) compilation warning if no assert_param check */ + UNUSED(Bank); + + /* Get the ECCR register value */ + *ECCval = (uint32_t)Device->ECCR; +#endif + + return HAL_OK; +} + +/** + * @} + */ +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + +#if defined(FMC_Bank4) + +/** @addtogroup FMC_LL_PCCARD + * @brief PCCARD Controller functions + * + @verbatim + ============================================================================== + ##### How to use PCCARD device driver ##### + ============================================================================== + [..] + This driver contains a set of APIs to interface with the FMC PCCARD bank in order + to run the PCCARD/compact flash external devices. + + (+) FMC PCCARD bank reset using the function FMC_PCCARD_DeInit() + (+) FMC PCCARD bank control configuration using the function FMC_PCCARD_Init() + (+) FMC PCCARD bank common space timing configuration using the function + FMC_PCCARD_CommonSpace_Timing_Init() + (+) FMC PCCARD bank attribute space timing configuration using the function + FMC_PCCARD_AttributeSpace_Timing_Init() + (+) FMC PCCARD bank IO space timing configuration using the function + FMC_PCCARD_IOSpace_Timing_Init() +@endverbatim + * @{ + */ + +/** @addtogroup FMC_LL_PCCARD_Private_Functions_Group1 + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FMC PCCARD interface + (+) De-initialize the FMC PCCARD interface + (+) Configure the FMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FMC_PCCARD device according to the specified + * control parameters in the FMC_PCCARD_HandleTypeDef + * @param Device Pointer to PCCARD device instance + * @param Init Pointer to PCCARD Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_PCCARD_Init(FMC_PCCARD_TypeDef *Device, FMC_PCCARD_InitTypeDef *Init) +{ + /* Check the parameters */ + assert_param(IS_FMC_PCCARD_DEVICE(Device)); +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + assert_param(IS_FMC_WAIT_FEATURE(Init->Waitfeature)); + assert_param(IS_FMC_TCLR_TIME(Init->TCLRSetupTime)); + assert_param(IS_FMC_TAR_TIME(Init->TARSetupTime)); +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + + /* Set FMC_PCCARD device control parameters */ + MODIFY_REG(Device->PCR4, + (FMC_PCR4_PTYP | + FMC_PCR4_PWAITEN | + FMC_PCR4_PWID | + FMC_PCR4_TCLR | + FMC_PCR4_TAR), + (FMC_PCR_MEMORY_TYPE_PCCARD | + Init->Waitfeature | + FMC_NAND_PCC_MEM_BUS_WIDTH_16 | + (Init->TCLRSetupTime << FMC_PCR4_TCLR_Pos) | + (Init->TARSetupTime << FMC_PCR4_TAR_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FMC_PCCARD Common space Timing according to the specified + * parameters in the FMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_PCCARD_CommonSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FMC_PCCARD_DEVICE(Device)); +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + + /* Set PCCARD timing parameters */ + MODIFY_REG(Device->PMEM4, PMEM4_CLEAR_MASK, + (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PMEM4_MEMWAIT4_Pos) | + ((Timing->HoldSetupTime) << FMC_PMEM4_MEMHOLD4_Pos) | + ((Timing->HiZSetupTime) << FMC_PMEM4_MEMHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FMC_PCCARD Attribute space Timing according to the specified + * parameters in the FMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_PCCARD_AttributeSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FMC_PCCARD_DEVICE(Device)); +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + + /* Set PCCARD timing parameters */ + MODIFY_REG(Device->PATT4, PATT4_CLEAR_MASK, + (Timing->SetupTime | + ((Timing->WaitSetupTime) << FMC_PATT4_ATTWAIT4_Pos) | + ((Timing->HoldSetupTime) << FMC_PATT4_ATTHOLD4_Pos) | + ((Timing->HiZSetupTime) << FMC_PATT4_ATTHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FMC_PCCARD IO space Timing according to the specified + * parameters in the FMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_PCCARD_IOSpace_Timing_Init(FMC_PCCARD_TypeDef *Device, + FMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FMC_PCCARD_DEVICE(Device)); +#if defined(FMC_Bank3) || defined(FMC_Bank2_3) + assert_param(IS_FMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FMC_Bank3) || defined(FMC_Bank2_3 */ + + /* Set FMC_PCCARD device timing parameters */ + MODIFY_REG(Device->PIO4, PIO4_CLEAR_MASK, + (Timing->SetupTime | + (Timing->WaitSetupTime << FMC_PIO4_IOWAIT4_Pos) | + (Timing->HoldSetupTime << FMC_PIO4_IOHOLD4_Pos) | + (Timing->HiZSetupTime << FMC_PIO4_IOHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief DeInitializes the FMC_PCCARD device + * @param Device Pointer to PCCARD device instance + * @retval HAL status + */ +HAL_StatusTypeDef FMC_PCCARD_DeInit(FMC_PCCARD_TypeDef *Device) +{ + /* Check the parameters */ + assert_param(IS_FMC_PCCARD_DEVICE(Device)); + + /* Disable the FMC_PCCARD device */ + __FMC_PCCARD_DISABLE(Device); + + /* De-initialize the FMC_PCCARD device */ + Device->PCR4 = 0x00000018U; + Device->SR4 = 0x00000040U; + Device->PMEM4 = 0xFCFCFCFCU; + Device->PATT4 = 0xFCFCFCFCU; + Device->PIO4 = 0xFCFCFCFCU; + + return HAL_OK; +} + +/** + * @} + */ +#endif /* FMC_Bank4 */ + +#if defined(FMC_Bank5_6) + +/** @defgroup FMC_LL_SDRAM + * @brief SDRAM Controller functions + * + @verbatim + ============================================================================== + ##### How to use SDRAM device driver ##### + ============================================================================== + [..] + This driver contains a set of APIs to interface with the FMC SDRAM banks in order + to run the SDRAM external devices. + + (+) FMC SDRAM bank reset using the function FMC_SDRAM_DeInit() + (+) FMC SDRAM bank control configuration using the function FMC_SDRAM_Init() + (+) FMC SDRAM bank timing configuration using the function FMC_SDRAM_Timing_Init() + (+) FMC SDRAM bank enable/disable write operation using the functions + FMC_SDRAM_WriteOperation_Enable()/FMC_SDRAM_WriteOperation_Disable() + (+) FMC SDRAM bank send command using the function FMC_SDRAM_SendCommand() + +@endverbatim + * @{ + */ + +/** @addtogroup FMC_LL_SDRAM_Private_Functions_Group1 + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FMC SDRAM interface + (+) De-initialize the FMC SDRAM interface + (+) Configure the FMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FMC_SDRAM device according to the specified + * control parameters in the FMC_SDRAM_InitTypeDef + * @param Device Pointer to SDRAM device instance + * @param Init Pointer to SDRAM Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDef *Init) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_SDRAM_BANK(Init->SDBank)); + assert_param(IS_FMC_COLUMNBITS_NUMBER(Init->ColumnBitsNumber)); + assert_param(IS_FMC_ROWBITS_NUMBER(Init->RowBitsNumber)); + assert_param(IS_FMC_SDMEMORY_WIDTH(Init->MemoryDataWidth)); + assert_param(IS_FMC_INTERNALBANK_NUMBER(Init->InternalBankNumber)); + assert_param(IS_FMC_CAS_LATENCY(Init->CASLatency)); + assert_param(IS_FMC_WRITE_PROTECTION(Init->WriteProtection)); + assert_param(IS_FMC_SDCLOCK_PERIOD(Init->SDClockPeriod)); + assert_param(IS_FMC_READ_BURST(Init->ReadBurst)); + assert_param(IS_FMC_READPIPE_DELAY(Init->ReadPipeDelay)); + + /* Set SDRAM bank configuration parameters */ + if (Init->SDBank == FMC_SDRAM_BANK1) + { + MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK1], + SDCR_CLEAR_MASK, + (Init->ColumnBitsNumber | + Init->RowBitsNumber | + Init->MemoryDataWidth | + Init->InternalBankNumber | + Init->CASLatency | + Init->WriteProtection | + Init->SDClockPeriod | + Init->ReadBurst | + Init->ReadPipeDelay)); + } + else /* FMC_Bank2_SDRAM */ + { + MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK1], + FMC_SDCR1_SDCLK | + FMC_SDCR1_RBURST | + FMC_SDCR1_RPIPE, + (Init->SDClockPeriod | + Init->ReadBurst | + Init->ReadPipeDelay)); + + MODIFY_REG(Device->SDCR[FMC_SDRAM_BANK2], + SDCR_CLEAR_MASK, + (Init->ColumnBitsNumber | + Init->RowBitsNumber | + Init->MemoryDataWidth | + Init->InternalBankNumber | + Init->CASLatency | + Init->WriteProtection)); + } + + return HAL_OK; +} + + +/** + * @brief Initializes the FMC_SDRAM device timing according to the specified + * parameters in the FMC_SDRAM_TimingTypeDef + * @param Device Pointer to SDRAM device instance + * @param Timing Pointer to SDRAM Timing structure + * @param Bank SDRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, + FMC_SDRAM_TimingTypeDef *Timing, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_LOADTOACTIVE_DELAY(Timing->LoadToActiveDelay)); + assert_param(IS_FMC_EXITSELFREFRESH_DELAY(Timing->ExitSelfRefreshDelay)); + assert_param(IS_FMC_SELFREFRESH_TIME(Timing->SelfRefreshTime)); + assert_param(IS_FMC_ROWCYCLE_DELAY(Timing->RowCycleDelay)); + assert_param(IS_FMC_WRITE_RECOVERY_TIME(Timing->WriteRecoveryTime)); + assert_param(IS_FMC_RP_DELAY(Timing->RPDelay)); + assert_param(IS_FMC_RCD_DELAY(Timing->RCDDelay)); + assert_param(IS_FMC_SDRAM_BANK(Bank)); + + /* Set SDRAM device timing parameters */ + if (Bank == FMC_SDRAM_BANK1) + { + MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK1], + SDTR_CLEAR_MASK, + (((Timing->LoadToActiveDelay) - 1U) | + (((Timing->ExitSelfRefreshDelay) - 1U) << FMC_SDTR1_TXSR_Pos) | + (((Timing->SelfRefreshTime) - 1U) << FMC_SDTR1_TRAS_Pos) | + (((Timing->RowCycleDelay) - 1U) << FMC_SDTR1_TRC_Pos) | + (((Timing->WriteRecoveryTime) - 1U) << FMC_SDTR1_TWR_Pos) | + (((Timing->RPDelay) - 1U) << FMC_SDTR1_TRP_Pos) | + (((Timing->RCDDelay) - 1U) << FMC_SDTR1_TRCD_Pos))); + } + else /* FMC_Bank2_SDRAM */ + { + MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK1], + FMC_SDTR1_TRC | + FMC_SDTR1_TRP, + (((Timing->RowCycleDelay) - 1U) << FMC_SDTR1_TRC_Pos) | + (((Timing->RPDelay) - 1U) << FMC_SDTR1_TRP_Pos)); + + MODIFY_REG(Device->SDTR[FMC_SDRAM_BANK2], + SDTR_CLEAR_MASK, + (((Timing->LoadToActiveDelay) - 1U) | + (((Timing->ExitSelfRefreshDelay) - 1U) << FMC_SDTR1_TXSR_Pos) | + (((Timing->SelfRefreshTime) - 1U) << FMC_SDTR1_TRAS_Pos) | + (((Timing->WriteRecoveryTime) - 1U) << FMC_SDTR1_TWR_Pos) | + (((Timing->RCDDelay) - 1U) << FMC_SDTR1_TRCD_Pos))); + } + + return HAL_OK; +} + +/** + * @brief DeInitializes the FMC_SDRAM peripheral + * @param Device Pointer to SDRAM device instance + * @retval HAL status + */ +HAL_StatusTypeDef FMC_SDRAM_DeInit(FMC_SDRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_SDRAM_BANK(Bank)); + + /* De-initialize the SDRAM device */ + Device->SDCR[Bank] = 0x000002D0U; + Device->SDTR[Bank] = 0x0FFFFFFFU; + Device->SDCMR = 0x00000000U; + Device->SDRTR = 0x00000000U; + Device->SDSR = 0x00000000U; + + return HAL_OK; +} + +/** + * @} + */ + +/** @addtogroup FMC_LL_SDRAMPrivate_Functions_Group2 + * @brief management functions + * +@verbatim + ============================================================================== + ##### FMC_SDRAM Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the FMC SDRAM interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically FMC_SDRAM write protection. + * @param Device Pointer to SDRAM device instance + * @param Bank SDRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Enable(FMC_SDRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_SDRAM_BANK(Bank)); + + /* Enable write protection */ + SET_BIT(Device->SDCR[Bank], FMC_SDRAM_WRITE_PROTECTION_ENABLE); + + return HAL_OK; +} + +/** + * @brief Disables dynamically FMC_SDRAM write protection. + * @param hsdram FMC_SDRAM handle + * @retval HAL status + */ +HAL_StatusTypeDef FMC_SDRAM_WriteProtection_Disable(FMC_SDRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_SDRAM_BANK(Bank)); + + /* Disable write protection */ + CLEAR_BIT(Device->SDCR[Bank], FMC_SDRAM_WRITE_PROTECTION_ENABLE); + + return HAL_OK; +} + +/** + * @brief Send Command to the FMC SDRAM bank + * @param Device Pointer to SDRAM device instance + * @param Command Pointer to SDRAM command structure + * @param Timing Pointer to SDRAM Timing structure + * @param Timeout Timeout wait value + * @retval HAL state + */ +HAL_StatusTypeDef FMC_SDRAM_SendCommand(FMC_SDRAM_TypeDef *Device, + FMC_SDRAM_CommandTypeDef *Command, uint32_t Timeout) +{ + uint32_t tickstart = 0U; + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_COMMAND_MODE(Command->CommandMode)); + assert_param(IS_FMC_COMMAND_TARGET(Command->CommandTarget)); + assert_param(IS_FMC_AUTOREFRESH_NUMBER(Command->AutoRefreshNumber)); + assert_param(IS_FMC_MODE_REGISTER(Command->ModeRegisterDefinition)); + + /* Set command register */ + MODIFY_REG(Device->SDCMR, (FMC_SDCMR_MODE | FMC_SDCMR_CTB2 | FMC_SDCMR_CTB1 | FMC_SDCMR_NRFS | FMC_SDCMR_MRD), + ((Command->CommandMode) | (Command->CommandTarget) | + (((Command->AutoRefreshNumber) - 1U) << FMC_SDCMR_NRFS_Pos) | + ((Command->ModeRegisterDefinition) << FMC_SDCMR_MRD_Pos))); + /* Get tick */ + tickstart = HAL_GetTick(); + + /* wait until command is send */ + while (HAL_IS_BIT_SET(Device->SDSR, FMC_SDSR_BUSY)) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout)) + { + return HAL_TIMEOUT; + } + } + } + return HAL_OK; +} + +/** + * @brief Program the SDRAM Memory Refresh rate. + * @param Device Pointer to SDRAM device instance + * @param RefreshRate The SDRAM refresh rate value. + * @retval HAL state + */ +HAL_StatusTypeDef FMC_SDRAM_ProgramRefreshRate(FMC_SDRAM_TypeDef *Device, uint32_t RefreshRate) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_REFRESH_RATE(RefreshRate)); + + /* Set the refresh rate in command register */ + MODIFY_REG(Device->SDRTR, FMC_SDRTR_COUNT, (RefreshRate << FMC_SDRTR_COUNT_Pos)); + + return HAL_OK; +} + +/** + * @brief Set the Number of consecutive SDRAM Memory auto Refresh commands. + * @param Device Pointer to SDRAM device instance + * @param AutoRefreshNumber Specifies the auto Refresh number. + * @retval None + */ +HAL_StatusTypeDef FMC_SDRAM_SetAutoRefreshNumber(FMC_SDRAM_TypeDef *Device, + uint32_t AutoRefreshNumber) +{ + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_AUTOREFRESH_NUMBER(AutoRefreshNumber)); + + /* Set the Auto-refresh number in command register */ + MODIFY_REG(Device->SDCMR, FMC_SDCMR_NRFS, ((AutoRefreshNumber - 1U) << FMC_SDCMR_NRFS_Pos)); + + return HAL_OK; +} + +/** + * @brief Returns the indicated FMC SDRAM bank mode status. + * @param Device Pointer to SDRAM device instance + * @param Bank Defines the FMC SDRAM bank. This parameter can be + * FMC_Bank1_SDRAM or FMC_Bank2_SDRAM. + * @retval The FMC SDRAM bank mode status, could be on of the following values: + * FMC_SDRAM_NORMAL_MODE, FMC_SDRAM_SELF_REFRESH_MODE or + * FMC_SDRAM_POWER_DOWN_MODE. + */ +uint32_t FMC_SDRAM_GetModeStatus(FMC_SDRAM_TypeDef *Device, uint32_t Bank) +{ + uint32_t tmpreg; + + /* Check the parameters */ + assert_param(IS_FMC_SDRAM_DEVICE(Device)); + assert_param(IS_FMC_SDRAM_BANK(Bank)); + + /* Get the corresponding bank mode */ + if (Bank == FMC_SDRAM_BANK1) + { + tmpreg = (uint32_t)(Device->SDSR & FMC_SDSR_MODES1); + } + else + { + tmpreg = ((uint32_t)(Device->SDSR & FMC_SDSR_MODES2) >> 2U); + } + + /* Return the mode status */ + return tmpreg; +} + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMC_Bank5_6 */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_NOR_MODULE_ENABLED */ +/** + * @} + */ +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c new file mode 100644 index 0000000..04966ea --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fmpi2c.c @@ -0,0 +1,217 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fmpi2c.c + * @author MCD Application Team + * @brief FMPI2C LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +#if defined(FMPI2C_CR1_PE) +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_fmpi2c.h" +#include "stm32f4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (FMPI2C1) + +/** @defgroup FMPI2C_LL FMPI2C + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup FMPI2C_LL_Private_Macros + * @{ + */ + +#define IS_LL_FMPI2C_PERIPHERAL_MODE(__VALUE__) (((__VALUE__) == LL_FMPI2C_MODE_I2C) || \ + ((__VALUE__) == LL_FMPI2C_MODE_SMBUS_HOST) || \ + ((__VALUE__) == LL_FMPI2C_MODE_SMBUS_DEVICE) || \ + ((__VALUE__) == LL_FMPI2C_MODE_SMBUS_DEVICE_ARP)) + +#define IS_LL_FMPI2C_ANALOG_FILTER(__VALUE__) (((__VALUE__) == LL_FMPI2C_ANALOGFILTER_ENABLE) || \ + ((__VALUE__) == LL_FMPI2C_ANALOGFILTER_DISABLE)) + +#define IS_LL_FMPI2C_DIGITAL_FILTER(__VALUE__) ((__VALUE__) <= 0x0000000FU) + +#define IS_LL_FMPI2C_OWN_ADDRESS1(__VALUE__) ((__VALUE__) <= 0x000003FFU) + +#define IS_LL_FMPI2C_TYPE_ACKNOWLEDGE(__VALUE__) (((__VALUE__) == LL_FMPI2C_ACK) || \ + ((__VALUE__) == LL_FMPI2C_NACK)) + +#define IS_LL_FMPI2C_OWN_ADDRSIZE(__VALUE__) (((__VALUE__) == LL_FMPI2C_OWNADDRESS1_7BIT) || \ + ((__VALUE__) == LL_FMPI2C_OWNADDRESS1_10BIT)) +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup FMPI2C_LL_Exported_Functions + * @{ + */ + +/** @addtogroup FMPI2C_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the FMPI2C registers to their default reset values. + * @param FMPI2Cx FMPI2C Instance. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: FMPI2C registers are de-initialized + * - ERROR: FMPI2C registers are not de-initialized + */ +ErrorStatus LL_FMPI2C_DeInit(FMPI2C_TypeDef *FMPI2Cx) +{ + ErrorStatus status = SUCCESS; + + /* Check the FMPI2C Instance FMPI2Cx */ + assert_param(IS_FMPI2C_ALL_INSTANCE(FMPI2Cx)); + + if (FMPI2Cx == FMPI2C1) + { + /* Force reset of FMPI2C clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_FMPI2C1); + + /* Release reset of FMPI2C clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_FMPI2C1); + } + else + { + status = ERROR; + } + + return status; +} + +/** + * @brief Initialize the FMPI2C registers according to the specified parameters in FMPI2C_InitStruct. + * @param FMPI2Cx FMPI2C Instance. + * @param FMPI2C_InitStruct pointer to a @ref LL_FMPI2C_InitTypeDef structure. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: FMPI2C registers are initialized + * - ERROR: Not applicable + */ +ErrorStatus LL_FMPI2C_Init(FMPI2C_TypeDef *FMPI2Cx, LL_FMPI2C_InitTypeDef *FMPI2C_InitStruct) +{ + /* Check the FMPI2C Instance FMPI2Cx */ + assert_param(IS_FMPI2C_ALL_INSTANCE(FMPI2Cx)); + + /* Check the FMPI2C parameters from FMPI2C_InitStruct */ + assert_param(IS_LL_FMPI2C_PERIPHERAL_MODE(FMPI2C_InitStruct->PeripheralMode)); + assert_param(IS_LL_FMPI2C_ANALOG_FILTER(FMPI2C_InitStruct->AnalogFilter)); + assert_param(IS_LL_FMPI2C_DIGITAL_FILTER(FMPI2C_InitStruct->DigitalFilter)); + assert_param(IS_LL_FMPI2C_OWN_ADDRESS1(FMPI2C_InitStruct->OwnAddress1)); + assert_param(IS_LL_FMPI2C_TYPE_ACKNOWLEDGE(FMPI2C_InitStruct->TypeAcknowledge)); + assert_param(IS_LL_FMPI2C_OWN_ADDRSIZE(FMPI2C_InitStruct->OwnAddrSize)); + + /* Disable the selected FMPI2Cx Peripheral */ + LL_FMPI2C_Disable(FMPI2Cx); + + /*---------------------------- FMPI2Cx CR1 Configuration ------------------------ + * Configure the analog and digital noise filters with parameters : + * - AnalogFilter: FMPI2C_CR1_ANFOFF bit + * - DigitalFilter: FMPI2C_CR1_DNF[3:0] bits + */ + LL_FMPI2C_ConfigFilters(FMPI2Cx, FMPI2C_InitStruct->AnalogFilter, FMPI2C_InitStruct->DigitalFilter); + + /*---------------------------- FMPI2Cx TIMINGR Configuration -------------------- + * Configure the SDA setup, hold time and the SCL high, low period with parameter : + * - Timing: FMPI2C_TIMINGR_PRESC[3:0], FMPI2C_TIMINGR_SCLDEL[3:0], FMPI2C_TIMINGR_SDADEL[3:0], + * FMPI2C_TIMINGR_SCLH[7:0] and FMPI2C_TIMINGR_SCLL[7:0] bits + */ + LL_FMPI2C_SetTiming(FMPI2Cx, FMPI2C_InitStruct->Timing); + + /* Enable the selected FMPI2Cx Peripheral */ + LL_FMPI2C_Enable(FMPI2Cx); + + /*---------------------------- FMPI2Cx OAR1 Configuration ----------------------- + * Disable, Configure and Enable FMPI2Cx device own address 1 with parameters : + * - OwnAddress1: FMPI2C_OAR1_OA1[9:0] bits + * - OwnAddrSize: FMPI2C_OAR1_OA1MODE bit + */ + LL_FMPI2C_DisableOwnAddress1(FMPI2Cx); + LL_FMPI2C_SetOwnAddress1(FMPI2Cx, FMPI2C_InitStruct->OwnAddress1, FMPI2C_InitStruct->OwnAddrSize); + + /* OwnAdress1 == 0 is reserved for General Call address */ + if (FMPI2C_InitStruct->OwnAddress1 != 0U) + { + LL_FMPI2C_EnableOwnAddress1(FMPI2Cx); + } + + /*---------------------------- FMPI2Cx MODE Configuration ----------------------- + * Configure FMPI2Cx peripheral mode with parameter : + * - PeripheralMode: FMPI2C_CR1_SMBDEN and FMPI2C_CR1_SMBHEN bits + */ + LL_FMPI2C_SetMode(FMPI2Cx, FMPI2C_InitStruct->PeripheralMode); + + /*---------------------------- FMPI2Cx CR2 Configuration ------------------------ + * Configure the ACKnowledge or Non ACKnowledge condition + * after the address receive match code or next received byte with parameter : + * - TypeAcknowledge: FMPI2C_CR2_NACK bit + */ + LL_FMPI2C_AcknowledgeNextData(FMPI2Cx, FMPI2C_InitStruct->TypeAcknowledge); + + return SUCCESS; +} + +/** + * @brief Set each @ref LL_FMPI2C_InitTypeDef field to default value. + * @param FMPI2C_InitStruct Pointer to a @ref LL_FMPI2C_InitTypeDef structure. + * @retval None + */ +void LL_FMPI2C_StructInit(LL_FMPI2C_InitTypeDef *FMPI2C_InitStruct) +{ + /* Set FMPI2C_InitStruct fields to default values */ + FMPI2C_InitStruct->PeripheralMode = LL_FMPI2C_MODE_I2C; + FMPI2C_InitStruct->Timing = 0U; + FMPI2C_InitStruct->AnalogFilter = LL_FMPI2C_ANALOGFILTER_ENABLE; + FMPI2C_InitStruct->DigitalFilter = 0U; + FMPI2C_InitStruct->OwnAddress1 = 0U; + FMPI2C_InitStruct->TypeAcknowledge = LL_FMPI2C_NACK; + FMPI2C_InitStruct->OwnAddrSize = LL_FMPI2C_OWNADDRESS1_7BIT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* FMPI2C1 */ + +/** + * @} + */ + +#endif /* FMPI2C_CR1_PE */ +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c new file mode 100644 index 0000000..8172871 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_fsmc.c @@ -0,0 +1,1062 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_fsmc.c + * @author MCD Application Team + * @brief FSMC Low Layer HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the Flexible Memory Controller (FSMC) peripheral memories: + * + Initialization/de-initialization functions + * + Peripheral Control functions + * + Peripheral State 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 + ============================================================================== + ##### FSMC peripheral features ##### + ============================================================================== + [..] The Flexible memory controller (FSMC) includes following memory controllers: + (+) The NOR/PSRAM memory controller + (+) The NAND/PC Card memory controller + + [..] The FSMC functional block makes the interface with synchronous and asynchronous static + memories and 16-bit PC memory cards. Its main purposes are: + (+) to translate AHB transactions into the appropriate external device protocol + (+) to meet the access time requirements of the external memory devices + + [..] All external memories share the addresses, data and control signals with the controller. + Each external device is accessed by means of a unique Chip Select. The FSMC performs + only one access at a time to an external device. + The main features of the FSMC controller are the following: + (+) Interface with static-memory mapped devices including: + (++) Static random access memory (SRAM) + (++) Read-only memory (ROM) + (++) NOR Flash memory/OneNAND Flash memory + (++) PSRAM (4 memory banks) + (++) 16-bit PC Card compatible devices + (++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of + data + (+) Independent Chip Select control for each memory bank + (+) Independent configuration for each memory bank + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#if defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_SRAM_MODULE_ENABLED) || defined(HAL_NAND_MODULE_ENABLED) || defined(HAL_PCCARD_MODULE_ENABLED) + +/** @defgroup FSMC_LL FSMC Low Layer + * @brief FSMC driver modules + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ + +/** @defgroup FSMC_LL_Private_Constants FSMC Low Layer Private Constants + * @{ + */ + +/* ----------------------- FSMC registers bit mask --------------------------- */ + +#if defined(FSMC_Bank1) +/* --- BCR Register ---*/ +/* BCR register clear mask */ + +/* --- BTR Register ---*/ +/* BTR register clear mask */ +#define BTR_CLEAR_MASK ((uint32_t)(FSMC_BTR1_ADDSET | FSMC_BTR1_ADDHLD |\ + FSMC_BTR1_DATAST | FSMC_BTR1_BUSTURN |\ + FSMC_BTR1_CLKDIV | FSMC_BTR1_DATLAT |\ + FSMC_BTR1_ACCMOD)) + +/* --- BWTR Register ---*/ +/* BWTR register clear mask */ +#define BWTR_CLEAR_MASK ((uint32_t)(FSMC_BWTR1_ADDSET | FSMC_BWTR1_ADDHLD |\ + FSMC_BWTR1_DATAST | FSMC_BWTR1_BUSTURN |\ + FSMC_BWTR1_ACCMOD)) +#endif /* FSMC_Bank1 */ +#if defined(FSMC_Bank2_3) + +#if defined (FSMC_PCR_PWAITEN) +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR_CLEAR_MASK ((uint32_t)(FSMC_PCR_PWAITEN | FSMC_PCR_PBKEN | \ + FSMC_PCR_PTYP | FSMC_PCR_PWID | \ + FSMC_PCR_ECCEN | FSMC_PCR_TCLR | \ + FSMC_PCR_TAR | FSMC_PCR_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM_CLEAR_MASK ((uint32_t)(FSMC_PMEM_MEMSET2 | FSMC_PMEM_MEMWAIT2 |\ + FSMC_PMEM_MEMHOLD2 | FSMC_PMEM_MEMHIZ2)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT_CLEAR_MASK ((uint32_t)(FSMC_PATT_ATTSET2 | FSMC_PATT_ATTWAIT2 |\ + FSMC_PATT_ATTHOLD2 | FSMC_PATT_ATTHIZ2)) +#else +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR_CLEAR_MASK ((uint32_t)(FSMC_PCR2_PWAITEN | FSMC_PCR2_PBKEN | \ + FSMC_PCR2_PTYP | FSMC_PCR2_PWID | \ + FSMC_PCR2_ECCEN | FSMC_PCR2_TCLR | \ + FSMC_PCR2_TAR | FSMC_PCR2_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM_CLEAR_MASK ((uint32_t)(FSMC_PMEM2_MEMSET2 | FSMC_PMEM2_MEMWAIT2 |\ + FSMC_PMEM2_MEMHOLD2 | FSMC_PMEM2_MEMHIZ2)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT_CLEAR_MASK ((uint32_t)(FSMC_PATT2_ATTSET2 | FSMC_PATT2_ATTWAIT2 |\ + FSMC_PATT2_ATTHOLD2 | FSMC_PATT2_ATTHIZ2)) + +#endif /* FSMC_PCR_PWAITEN */ +#endif /* FSMC_Bank2_3 */ +#if defined(FSMC_Bank4) +/* --- PCR Register ---*/ +/* PCR register clear mask */ +#define PCR4_CLEAR_MASK ((uint32_t)(FSMC_PCR4_PWAITEN | FSMC_PCR4_PBKEN | \ + FSMC_PCR4_PTYP | FSMC_PCR4_PWID | \ + FSMC_PCR4_ECCEN | FSMC_PCR4_TCLR | \ + FSMC_PCR4_TAR | FSMC_PCR4_ECCPS)) +/* --- PMEM Register ---*/ +/* PMEM register clear mask */ +#define PMEM4_CLEAR_MASK ((uint32_t)(FSMC_PMEM4_MEMSET4 | FSMC_PMEM4_MEMWAIT4 |\ + FSMC_PMEM4_MEMHOLD4 | FSMC_PMEM4_MEMHIZ4)) + +/* --- PATT Register ---*/ +/* PATT register clear mask */ +#define PATT4_CLEAR_MASK ((uint32_t)(FSMC_PATT4_ATTSET4 | FSMC_PATT4_ATTWAIT4 |\ + FSMC_PATT4_ATTHOLD4 | FSMC_PATT4_ATTHIZ4)) + +/* --- PIO4 Register ---*/ +/* PIO4 register clear mask */ +#define PIO4_CLEAR_MASK ((uint32_t)(FSMC_PIO4_IOSET4 | FSMC_PIO4_IOWAIT4 | \ + FSMC_PIO4_IOHOLD4 | FSMC_PIO4_IOHIZ4)) + +#endif /* FSMC_Bank4 */ + +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup FSMC_LL_Exported_Functions FSMC Low Layer Exported Functions + * @{ + */ + +#if defined(FSMC_Bank1) + +/** @defgroup FSMC_LL_Exported_Functions_NORSRAM FSMC Low Layer NOR SRAM Exported Functions + * @brief NORSRAM Controller functions + * + @verbatim + ============================================================================== + ##### How to use NORSRAM device driver ##### + ============================================================================== + + [..] + This driver contains a set of APIs to interface with the FSMC NORSRAM banks in order + to run the NORSRAM external devices. + + (+) FSMC NORSRAM bank reset using the function FSMC_NORSRAM_DeInit() + (+) FSMC NORSRAM bank control configuration using the function FSMC_NORSRAM_Init() + (+) FSMC NORSRAM bank timing configuration using the function FSMC_NORSRAM_Timing_Init() + (+) FSMC NORSRAM bank extended timing configuration using the function + FSMC_NORSRAM_Extended_Timing_Init() + (+) FSMC NORSRAM bank enable/disable write operation using the functions + FSMC_NORSRAM_WriteOperation_Enable()/FSMC_NORSRAM_WriteOperation_Disable() + +@endverbatim + * @{ + */ + +/** @defgroup FSMC_LL_NORSRAM_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * + @verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FSMC NORSRAM interface + (+) De-initialize the FSMC NORSRAM interface + (+) Configure the FSMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the FSMC_NORSRAM device according to the specified + * control parameters in the FSMC_NORSRAM_InitTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Init Pointer to NORSRAM Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_Init(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_InitTypeDef *Init) +{ + uint32_t flashaccess; + uint32_t btcr_reg; + uint32_t mask; + + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FSMC_NORSRAM_BANK(Init->NSBank)); + assert_param(IS_FSMC_MUX(Init->DataAddressMux)); + assert_param(IS_FSMC_MEMORY(Init->MemoryType)); + assert_param(IS_FSMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth)); + assert_param(IS_FSMC_BURSTMODE(Init->BurstAccessMode)); + assert_param(IS_FSMC_WAIT_POLARITY(Init->WaitSignalPolarity)); +#if defined(FSMC_BCR1_WRAPMOD) + assert_param(IS_FSMC_WRAP_MODE(Init->WrapMode)); +#endif /* FSMC_BCR1_WRAPMOD */ + assert_param(IS_FSMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive)); + assert_param(IS_FSMC_WRITE_OPERATION(Init->WriteOperation)); + assert_param(IS_FSMC_WAITE_SIGNAL(Init->WaitSignal)); + assert_param(IS_FSMC_EXTENDED_MODE(Init->ExtendedMode)); + assert_param(IS_FSMC_ASYNWAIT(Init->AsynchronousWait)); + assert_param(IS_FSMC_WRITE_BURST(Init->WriteBurst)); +#if defined(FSMC_BCR1_CCLKEN) + assert_param(IS_FSMC_CONTINOUS_CLOCK(Init->ContinuousClock)); +#endif +#if defined(FSMC_BCR1_WFDIS) + assert_param(IS_FSMC_WRITE_FIFO(Init->WriteFifo)); +#endif /* FSMC_BCR1_WFDIS */ + assert_param(IS_FSMC_PAGESIZE(Init->PageSize)); + + /* Disable NORSRAM Device */ + __FSMC_NORSRAM_DISABLE(Device, Init->NSBank); + + /* Set NORSRAM device control parameters */ + if (Init->MemoryType == FSMC_MEMORY_TYPE_NOR) + { + flashaccess = FSMC_NORSRAM_FLASH_ACCESS_ENABLE; + } + else + { + flashaccess = FSMC_NORSRAM_FLASH_ACCESS_DISABLE; + } + + btcr_reg = (flashaccess | \ + Init->DataAddressMux | \ + Init->MemoryType | \ + Init->MemoryDataWidth | \ + Init->BurstAccessMode | \ + Init->WaitSignalPolarity | \ + Init->WaitSignalActive | \ + Init->WriteOperation | \ + Init->WaitSignal | \ + Init->ExtendedMode | \ + Init->AsynchronousWait | \ + Init->WriteBurst); + +#if defined(FSMC_BCR1_WRAPMOD) + btcr_reg |= Init->WrapMode; +#endif /* FSMC_BCR1_WRAPMOD */ +#if defined(FSMC_BCR1_CCLKEN) + btcr_reg |= Init->ContinuousClock; +#endif /* FSMC_BCR1_CCLKEN */ +#if defined(FSMC_BCR1_WFDIS) + btcr_reg |= Init->WriteFifo; +#endif /* FSMC_BCR1_WFDIS */ + btcr_reg |= Init->PageSize; + + mask = (FSMC_BCR1_MBKEN | + FSMC_BCR1_MUXEN | + FSMC_BCR1_MTYP | + FSMC_BCR1_MWID | + FSMC_BCR1_FACCEN | + FSMC_BCR1_BURSTEN | + FSMC_BCR1_WAITPOL | + FSMC_BCR1_WAITCFG | + FSMC_BCR1_WREN | + FSMC_BCR1_WAITEN | + FSMC_BCR1_EXTMOD | + FSMC_BCR1_ASYNCWAIT | + FSMC_BCR1_CBURSTRW); + +#if defined(FSMC_BCR1_WRAPMOD) + mask |= FSMC_BCR1_WRAPMOD; +#endif /* FSMC_BCR1_WRAPMOD */ +#if defined(FSMC_BCR1_CCLKEN) + mask |= FSMC_BCR1_CCLKEN; +#endif +#if defined(FSMC_BCR1_WFDIS) + mask |= FSMC_BCR1_WFDIS; +#endif /* FSMC_BCR1_WFDIS */ + mask |= FSMC_BCR1_CPSIZE; + + MODIFY_REG(Device->BTCR[Init->NSBank], mask, btcr_reg); + +#if defined(FSMC_BCR1_CCLKEN) + /* Configure synchronous mode when Continuous clock is enabled for bank2..4 */ + if ((Init->ContinuousClock == FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC) && (Init->NSBank != FSMC_NORSRAM_BANK1)) + { + MODIFY_REG(Device->BTCR[FSMC_NORSRAM_BANK1], FSMC_BCR1_CCLKEN, Init->ContinuousClock); + } +#endif +#if defined(FSMC_BCR1_WFDIS) + + if (Init->NSBank != FSMC_NORSRAM_BANK1) + { + /* Configure Write FIFO mode when Write Fifo is enabled for bank2..4 */ + SET_BIT(Device->BTCR[FSMC_NORSRAM_BANK1], (uint32_t)(Init->WriteFifo)); + } +#endif /* FSMC_BCR1_WFDIS */ + + return HAL_OK; +} + +/** + * @brief DeInitialize the FSMC_NORSRAM peripheral + * @param Device Pointer to NORSRAM device instance + * @param ExDevice Pointer to NORSRAM extended mode device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_DeInit(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(ExDevice)); + assert_param(IS_FSMC_NORSRAM_BANK(Bank)); + + /* Disable the FSMC_NORSRAM device */ + __FSMC_NORSRAM_DISABLE(Device, Bank); + + /* De-initialize the FSMC_NORSRAM device */ + /* FSMC_NORSRAM_BANK1 */ + if (Bank == FSMC_NORSRAM_BANK1) + { + Device->BTCR[Bank] = 0x000030DBU; + } + /* FSMC_NORSRAM_BANK2, FSMC_NORSRAM_BANK3 or FSMC_NORSRAM_BANK4 */ + else + { + Device->BTCR[Bank] = 0x000030D2U; + } + + Device->BTCR[Bank + 1U] = 0x0FFFFFFFU; + ExDevice->BWTR[Bank] = 0x0FFFFFFFU; + + return HAL_OK; +} + +/** + * @brief Initialize the FSMC_NORSRAM Timing according to the specified + * parameters in the FSMC_NORSRAM_TimingTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Timing Pointer to NORSRAM Timing structure + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_Timing_Init(FSMC_NORSRAM_TypeDef *Device, + FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank) +{ +#if defined(FSMC_BCR1_CCLKEN) + uint32_t tmpr; +#endif + + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime)); + assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime)); + assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime)); + assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration)); + assert_param(IS_FSMC_CLK_DIV(Timing->CLKDivision)); + assert_param(IS_FSMC_DATA_LATENCY(Timing->DataLatency)); + assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode)); + assert_param(IS_FSMC_NORSRAM_BANK(Bank)); + + /* Set FSMC_NORSRAM device timing parameters */ + MODIFY_REG(Device->BTCR[Bank + 1U], BTR_CLEAR_MASK, (Timing->AddressSetupTime | + ((Timing->AddressHoldTime) << FSMC_BTR1_ADDHLD_Pos) | + ((Timing->DataSetupTime) << FSMC_BTR1_DATAST_Pos) | + ((Timing->BusTurnAroundDuration) << FSMC_BTR1_BUSTURN_Pos) | + (((Timing->CLKDivision) - 1U) << FSMC_BTR1_CLKDIV_Pos) | + (((Timing->DataLatency) - 2U) << FSMC_BTR1_DATLAT_Pos) | + (Timing->AccessMode))); + +#if defined(FSMC_BCR1_CCLKEN) + /* Configure Clock division value (in NORSRAM bank 1) when continuous clock is enabled */ + if (HAL_IS_BIT_SET(Device->BTCR[FSMC_NORSRAM_BANK1], FSMC_BCR1_CCLKEN)) + { + tmpr = (uint32_t)(Device->BTCR[FSMC_NORSRAM_BANK1 + 1U] & ~((0x0FU) << FSMC_BTR1_CLKDIV_Pos)); + tmpr |= (uint32_t)(((Timing->CLKDivision) - 1U) << FSMC_BTR1_CLKDIV_Pos); + MODIFY_REG(Device->BTCR[FSMC_NORSRAM_BANK1 + 1U], FSMC_BTR1_CLKDIV, tmpr); + } + +#endif + return HAL_OK; +} + +/** + * @brief Initialize the FSMC_NORSRAM Extended mode Timing according to the specified + * parameters in the FSMC_NORSRAM_TimingTypeDef + * @param Device Pointer to NORSRAM device instance + * @param Timing Pointer to NORSRAM Timing structure + * @param Bank NORSRAM bank number + * @param ExtendedMode FSMC Extended Mode + * This parameter can be one of the following values: + * @arg FSMC_EXTENDED_MODE_DISABLE + * @arg FSMC_EXTENDED_MODE_ENABLE + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_Extended_Timing_Init(FSMC_NORSRAM_EXTENDED_TypeDef *Device, + FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank, + uint32_t ExtendedMode) +{ + /* Check the parameters */ + assert_param(IS_FSMC_EXTENDED_MODE(ExtendedMode)); + + /* Set NORSRAM device timing register for write configuration, if extended mode is used */ + if (ExtendedMode == FSMC_EXTENDED_MODE_ENABLE) + { + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(Device)); + assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime)); + assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime)); + assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime)); + assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration)); + assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode)); + assert_param(IS_FSMC_NORSRAM_BANK(Bank)); + + /* Set NORSRAM device timing register for write configuration, if extended mode is used */ + MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime | + ((Timing->AddressHoldTime) << FSMC_BWTR1_ADDHLD_Pos) | + ((Timing->DataSetupTime) << FSMC_BWTR1_DATAST_Pos) | + Timing->AccessMode | + ((Timing->BusTurnAroundDuration) << FSMC_BWTR1_BUSTURN_Pos))); + } + else + { + Device->BWTR[Bank] = 0x0FFFFFFFU; + } + + return HAL_OK; +} +/** + * @} + */ + +/** @addtogroup FSMC_LL_NORSRAM_Private_Functions_Group2 + * @brief management functions + * +@verbatim + ============================================================================== + ##### FSMC_NORSRAM Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the FSMC NORSRAM interface. + +@endverbatim + * @{ + */ + +/** + * @brief Enables dynamically FSMC_NORSRAM write operation. + * @param Device Pointer to NORSRAM device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Enable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FSMC_NORSRAM_BANK(Bank)); + + /* Enable write operation */ + SET_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE); + + return HAL_OK; +} + +/** + * @brief Disables dynamically FSMC_NORSRAM write operation. + * @param Device Pointer to NORSRAM device instance + * @param Bank NORSRAM bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Disable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NORSRAM_DEVICE(Device)); + assert_param(IS_FSMC_NORSRAM_BANK(Bank)); + + /* Disable write operation */ + CLEAR_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE); + + return HAL_OK; +} + +/** + * @} + */ + +/** + * @} + */ +#endif /* FSMC_Bank1 */ + +#if defined(FSMC_Bank2_3) + +/** @defgroup FSMC_LL_Exported_Functions_NAND FSMC Low Layer NAND Exported Functions + * @brief NAND Controller functions + * + @verbatim + ============================================================================== + ##### How to use NAND device driver ##### + ============================================================================== + [..] + This driver contains a set of APIs to interface with the FSMC NAND banks in order + to run the NAND external devices. + + (+) FSMC NAND bank reset using the function FSMC_NAND_DeInit() + (+) FSMC NAND bank control configuration using the function FSMC_NAND_Init() + (+) FSMC NAND bank common space timing configuration using the function + FSMC_NAND_CommonSpace_Timing_Init() + (+) FSMC NAND bank attribute space timing configuration using the function + FSMC_NAND_AttributeSpace_Timing_Init() + (+) FSMC NAND bank enable/disable ECC correction feature using the functions + FSMC_NAND_ECC_Enable()/FSMC_NAND_ECC_Disable() + (+) FSMC NAND bank get ECC correction code using the function FSMC_NAND_GetECC() + +@endverbatim + * @{ + */ + +/** @defgroup FSMC_LL_NAND_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FSMC NAND interface + (+) De-initialize the FSMC NAND interface + (+) Configure the FSMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FSMC_NAND device according to the specified + * control parameters in the FSMC_NAND_HandleTypeDef + * @param Device Pointer to NAND device instance + * @param Init Pointer to NAND Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_Init(FSMC_NAND_TypeDef *Device, FSMC_NAND_InitTypeDef *Init) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_NAND_BANK(Init->NandBank)); + assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature)); + assert_param(IS_FSMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth)); + assert_param(IS_FSMC_ECC_STATE(Init->EccComputation)); + assert_param(IS_FSMC_ECCPAGE_SIZE(Init->ECCPageSize)); + assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime)); + assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime)); + + /* Set NAND device control parameters */ + if (Init->NandBank == FSMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PCR2, PCR_CLEAR_MASK, (Init->Waitfeature | + FSMC_PCR_MEMORY_TYPE_NAND | + Init->MemoryDataWidth | + Init->EccComputation | + Init->ECCPageSize | + ((Init->TCLRSetupTime) << FSMC_PCR2_TCLR_Pos) | + ((Init->TARSetupTime) << FSMC_PCR2_TAR_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PCR3, PCR_CLEAR_MASK, (Init->Waitfeature | + FSMC_PCR_MEMORY_TYPE_NAND | + Init->MemoryDataWidth | + Init->EccComputation | + Init->ECCPageSize | + ((Init->TCLRSetupTime) << FSMC_PCR2_TCLR_Pos) | + ((Init->TARSetupTime) << FSMC_PCR2_TAR_Pos))); + } + + return HAL_OK; +} + +/** + * @brief Initializes the FSMC_NAND Common space Timing according to the specified + * parameters in the FSMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to NAND device instance + * @param Timing Pointer to NAND timing structure + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_CommonSpace_Timing_Init(FSMC_NAND_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Set FSMC_NAND device timing parameters */ + if (Bank == FSMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PMEM2, PMEM_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PMEM2_MEMWAIT2_Pos) | + ((Timing->HoldSetupTime) << FSMC_PMEM2_MEMHOLD2_Pos) | + ((Timing->HiZSetupTime) << FSMC_PMEM2_MEMHIZ2_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PMEM3, PMEM_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PMEM2_MEMWAIT2_Pos) | + ((Timing->HoldSetupTime) << FSMC_PMEM2_MEMHOLD2_Pos) | + ((Timing->HiZSetupTime) << FSMC_PMEM2_MEMHIZ2_Pos))); + } + + return HAL_OK; +} + +/** + * @brief Initializes the FSMC_NAND Attribute space Timing according to the specified + * parameters in the FSMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to NAND device instance + * @param Timing Pointer to NAND timing structure + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_AttributeSpace_Timing_Init(FSMC_NAND_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Set FSMC_NAND device timing parameters */ + if (Bank == FSMC_NAND_BANK2) + { + /* NAND bank 2 registers configuration */ + MODIFY_REG(Device->PATT2, PATT_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PATT2_ATTWAIT2_Pos) | + ((Timing->HoldSetupTime) << FSMC_PATT2_ATTHOLD2_Pos) | + ((Timing->HiZSetupTime) << FSMC_PATT2_ATTHIZ2_Pos))); + } + else + { + /* NAND bank 3 registers configuration */ + MODIFY_REG(Device->PATT3, PATT_CLEAR_MASK, (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PATT2_ATTWAIT2_Pos) | + ((Timing->HoldSetupTime) << FSMC_PATT2_ATTHOLD2_Pos) | + ((Timing->HiZSetupTime) << FSMC_PATT2_ATTHIZ2_Pos))); + } + + return HAL_OK; +} + +/** + * @brief DeInitializes the FSMC_NAND device + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_DeInit(FSMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Disable the NAND Bank */ + __FSMC_NAND_DISABLE(Device, Bank); + + /* De-initialize the NAND Bank */ + if (Bank == FSMC_NAND_BANK2) + { + /* Set the FSMC_NAND_BANK2 registers to their reset values */ + WRITE_REG(Device->PCR2, 0x00000018U); + WRITE_REG(Device->SR2, 0x00000040U); + WRITE_REG(Device->PMEM2, 0xFCFCFCFCU); + WRITE_REG(Device->PATT2, 0xFCFCFCFCU); + } + /* FSMC_Bank3_NAND */ + else + { + /* Set the FSMC_NAND_BANK3 registers to their reset values */ + WRITE_REG(Device->PCR3, 0x00000018U); + WRITE_REG(Device->SR3, 0x00000040U); + WRITE_REG(Device->PMEM3, 0xFCFCFCFCU); + WRITE_REG(Device->PATT3, 0xFCFCFCFCU); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup HAL_FSMC_NAND_Group2 Peripheral Control functions + * @brief management functions + * +@verbatim + ============================================================================== + ##### FSMC_NAND Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control dynamically + the FSMC NAND interface. + +@endverbatim + * @{ + */ + + +/** + * @brief Enables dynamically FSMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_ECC_Enable(FSMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Enable ECC feature */ + if (Bank == FSMC_NAND_BANK2) + { + SET_BIT(Device->PCR2, FSMC_PCR2_ECCEN); + } + else + { + SET_BIT(Device->PCR3, FSMC_PCR2_ECCEN); + } + + return HAL_OK; +} + + +/** + * @brief Disables dynamically FSMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param Bank NAND bank number + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_ECC_Disable(FSMC_NAND_TypeDef *Device, uint32_t Bank) +{ + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Disable ECC feature */ + if (Bank == FSMC_NAND_BANK2) + { + CLEAR_BIT(Device->PCR2, FSMC_PCR2_ECCEN); + } + else + { + CLEAR_BIT(Device->PCR3, FSMC_PCR2_ECCEN); + } + + return HAL_OK; +} + +/** + * @brief Disables dynamically FSMC_NAND ECC feature. + * @param Device Pointer to NAND device instance + * @param ECCval Pointer to ECC value + * @param Bank NAND bank number + * @param Timeout Timeout wait value + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_NAND_GetECC(FSMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank, + uint32_t Timeout) +{ + uint32_t tickstart; + + /* Check the parameters */ + assert_param(IS_FSMC_NAND_DEVICE(Device)); + assert_param(IS_FSMC_NAND_BANK(Bank)); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait until FIFO is empty */ + while (__FSMC_NAND_GET_FLAG(Device, Bank, FSMC_FLAG_FEMPT) == RESET) + { + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + return HAL_TIMEOUT; + } + } + } + + if (Bank == FSMC_NAND_BANK2) + { + /* Get the ECCR2 register value */ + *ECCval = (uint32_t)Device->ECCR2; + } + else + { + /* Get the ECCR3 register value */ + *ECCval = (uint32_t)Device->ECCR3; + } + + return HAL_OK; +} + +/** + * @} + */ +#endif /* FSMC_Bank2_3 */ + +#if defined(FSMC_Bank4) + +/** @addtogroup FSMC_LL_PCCARD + * @brief PCCARD Controller functions + * + @verbatim + ============================================================================== + ##### How to use PCCARD device driver ##### + ============================================================================== + [..] + This driver contains a set of APIs to interface with the FSMC PCCARD bank in order + to run the PCCARD/compact flash external devices. + + (+) FSMC PCCARD bank reset using the function FSMC_PCCARD_DeInit() + (+) FSMC PCCARD bank control configuration using the function FSMC_PCCARD_Init() + (+) FSMC PCCARD bank common space timing configuration using the function + FSMC_PCCARD_CommonSpace_Timing_Init() + (+) FSMC PCCARD bank attribute space timing configuration using the function + FSMC_PCCARD_AttributeSpace_Timing_Init() + (+) FSMC PCCARD bank IO space timing configuration using the function + FSMC_PCCARD_IOSpace_Timing_Init() +@endverbatim + * @{ + */ + +/** @addtogroup FSMC_LL_PCCARD_Private_Functions_Group1 + * @brief Initialization and Configuration functions + * +@verbatim + ============================================================================== + ##### Initialization and de_initialization functions ##### + ============================================================================== + [..] + This section provides functions allowing to: + (+) Initialize and configure the FSMC PCCARD interface + (+) De-initialize the FSMC PCCARD interface + (+) Configure the FSMC clock and associated GPIOs + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the FSMC_PCCARD device according to the specified + * control parameters in the FSMC_PCCARD_HandleTypeDef + * @param Device Pointer to PCCARD device instance + * @param Init Pointer to PCCARD Initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_PCCARD_Init(FSMC_PCCARD_TypeDef *Device, FSMC_PCCARD_InitTypeDef *Init) +{ + /* Check the parameters */ + assert_param(IS_FSMC_PCCARD_DEVICE(Device)); +#if defined(FSMC_Bank2_3) + assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature)); + assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime)); + assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime)); +#endif /* FSMC_Bank2_3 */ + + /* Set FSMC_PCCARD device control parameters */ + MODIFY_REG(Device->PCR4, + (FSMC_PCR4_PTYP | + FSMC_PCR4_PWAITEN | + FSMC_PCR4_PWID | + FSMC_PCR4_TCLR | + FSMC_PCR4_TAR), + (FSMC_PCR_MEMORY_TYPE_PCCARD | + Init->Waitfeature | + FSMC_NAND_PCC_MEM_BUS_WIDTH_16 | + (Init->TCLRSetupTime << FSMC_PCR4_TCLR_Pos) | + (Init->TARSetupTime << FSMC_PCR4_TAR_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FSMC_PCCARD Common space Timing according to the specified + * parameters in the FSMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_PCCARD_CommonSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FSMC_PCCARD_DEVICE(Device)); +#if defined(FSMC_Bank2_3) + assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FSMC_Bank2_3 */ + + /* Set PCCARD timing parameters */ + MODIFY_REG(Device->PMEM4, PMEM4_CLEAR_MASK, + (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PMEM4_MEMWAIT4_Pos) | + ((Timing->HoldSetupTime) << FSMC_PMEM4_MEMHOLD4_Pos) | + ((Timing->HiZSetupTime) << FSMC_PMEM4_MEMHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FSMC_PCCARD Attribute space Timing according to the specified + * parameters in the FSMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_PCCARD_AttributeSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FSMC_PCCARD_DEVICE(Device)); +#if defined(FSMC_Bank2_3) + assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FSMC_Bank2_3 */ + + /* Set PCCARD timing parameters */ + MODIFY_REG(Device->PATT4, PATT4_CLEAR_MASK, + (Timing->SetupTime | + ((Timing->WaitSetupTime) << FSMC_PATT4_ATTWAIT4_Pos) | + ((Timing->HoldSetupTime) << FSMC_PATT4_ATTHOLD4_Pos) | + ((Timing->HiZSetupTime) << FSMC_PATT4_ATTHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief Initializes the FSMC_PCCARD IO space Timing according to the specified + * parameters in the FSMC_NAND_PCC_TimingTypeDef + * @param Device Pointer to PCCARD device instance + * @param Timing Pointer to PCCARD timing structure + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_PCCARD_IOSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device, + FSMC_NAND_PCC_TimingTypeDef *Timing) +{ + /* Check the parameters */ + assert_param(IS_FSMC_PCCARD_DEVICE(Device)); +#if defined(FSMC_Bank2_3) + assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime)); + assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime)); + assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime)); + assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime)); +#endif /* FSMC_Bank2_3 */ + + /* Set FSMC_PCCARD device timing parameters */ + MODIFY_REG(Device->PIO4, PIO4_CLEAR_MASK, + (Timing->SetupTime | + (Timing->WaitSetupTime << FSMC_PIO4_IOWAIT4_Pos) | + (Timing->HoldSetupTime << FSMC_PIO4_IOHOLD4_Pos) | + (Timing->HiZSetupTime << FSMC_PIO4_IOHIZ4_Pos))); + + return HAL_OK; +} + +/** + * @brief DeInitializes the FSMC_PCCARD device + * @param Device Pointer to PCCARD device instance + * @retval HAL status + */ +HAL_StatusTypeDef FSMC_PCCARD_DeInit(FSMC_PCCARD_TypeDef *Device) +{ + /* Check the parameters */ + assert_param(IS_FSMC_PCCARD_DEVICE(Device)); + + /* Disable the FSMC_PCCARD device */ + __FSMC_PCCARD_DISABLE(Device); + + /* De-initialize the FSMC_PCCARD device */ + Device->PCR4 = 0x00000018U; + Device->SR4 = 0x00000040U; + Device->PMEM4 = 0xFCFCFCFCU; + Device->PATT4 = 0xFCFCFCFCU; + Device->PIO4 = 0xFCFCFCFCU; + + return HAL_OK; +} + +/** + * @} + */ +#endif /* FSMC_Bank4 */ + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* HAL_NOR_MODULE_ENABLED */ +/** + * @} + */ +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c new file mode 100644 index 0000000..4d100b5 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c @@ -0,0 +1,303 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_gpio.c + * @author MCD Application Team + * @brief GPIO LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_gpio.h" +#include "stm32f4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) || defined (GPIOJ) || defined (GPIOK) + +/** @addtogroup GPIO_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup GPIO_LL_Private_Macros + * @{ + */ +#define IS_LL_GPIO_PIN(__VALUE__) (((0x00000000U) < (__VALUE__)) && ((__VALUE__) <= (LL_GPIO_PIN_ALL))) + +#define IS_LL_GPIO_MODE(__VALUE__) (((__VALUE__) == LL_GPIO_MODE_INPUT) ||\ + ((__VALUE__) == LL_GPIO_MODE_OUTPUT) ||\ + ((__VALUE__) == LL_GPIO_MODE_ALTERNATE) ||\ + ((__VALUE__) == LL_GPIO_MODE_ANALOG)) + +#define IS_LL_GPIO_OUTPUT_TYPE(__VALUE__) (((__VALUE__) == LL_GPIO_OUTPUT_PUSHPULL) ||\ + ((__VALUE__) == LL_GPIO_OUTPUT_OPENDRAIN)) + +#define IS_LL_GPIO_SPEED(__VALUE__) (((__VALUE__) == LL_GPIO_SPEED_FREQ_LOW) ||\ + ((__VALUE__) == LL_GPIO_SPEED_FREQ_MEDIUM) ||\ + ((__VALUE__) == LL_GPIO_SPEED_FREQ_HIGH) ||\ + ((__VALUE__) == LL_GPIO_SPEED_FREQ_VERY_HIGH)) + +#define IS_LL_GPIO_PULL(__VALUE__) (((__VALUE__) == LL_GPIO_PULL_NO) ||\ + ((__VALUE__) == LL_GPIO_PULL_UP) ||\ + ((__VALUE__) == LL_GPIO_PULL_DOWN)) + +#define IS_LL_GPIO_ALTERNATE(__VALUE__) (((__VALUE__) == LL_GPIO_AF_0 ) ||\ + ((__VALUE__) == LL_GPIO_AF_1 ) ||\ + ((__VALUE__) == LL_GPIO_AF_2 ) ||\ + ((__VALUE__) == LL_GPIO_AF_3 ) ||\ + ((__VALUE__) == LL_GPIO_AF_4 ) ||\ + ((__VALUE__) == LL_GPIO_AF_5 ) ||\ + ((__VALUE__) == LL_GPIO_AF_6 ) ||\ + ((__VALUE__) == LL_GPIO_AF_7 ) ||\ + ((__VALUE__) == LL_GPIO_AF_8 ) ||\ + ((__VALUE__) == LL_GPIO_AF_9 ) ||\ + ((__VALUE__) == LL_GPIO_AF_10 ) ||\ + ((__VALUE__) == LL_GPIO_AF_11 ) ||\ + ((__VALUE__) == LL_GPIO_AF_12 ) ||\ + ((__VALUE__) == LL_GPIO_AF_13 ) ||\ + ((__VALUE__) == LL_GPIO_AF_14 ) ||\ + ((__VALUE__) == LL_GPIO_AF_15 )) +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup GPIO_LL_Exported_Functions + * @{ + */ + +/** @addtogroup GPIO_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize GPIO registers (Registers restored to their default values). + * @param GPIOx GPIO Port + * @retval An ErrorStatus enumeration value: + * - SUCCESS: GPIO registers are de-initialized + * - ERROR: Wrong GPIO Port + */ +ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + + /* Force and Release reset on clock of GPIOx Port */ + if (GPIOx == GPIOA) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOA); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOA); + } + else if (GPIOx == GPIOB) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOB); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOB); + } + else if (GPIOx == GPIOC) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOC); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOC); + } +#if defined(GPIOD) + else if (GPIOx == GPIOD) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOD); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOD); + } +#endif /* GPIOD */ +#if defined(GPIOE) + else if (GPIOx == GPIOE) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOE); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOE); + } +#endif /* GPIOE */ +#if defined(GPIOF) + else if (GPIOx == GPIOF) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOF); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOF); + } +#endif /* GPIOF */ +#if defined(GPIOG) + else if (GPIOx == GPIOG) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOG); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOG); + } +#endif /* GPIOG */ +#if defined(GPIOH) + else if (GPIOx == GPIOH) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOH); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOH); + } +#endif /* GPIOH */ +#if defined(GPIOI) + else if (GPIOx == GPIOI) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOI); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOI); + } +#endif /* GPIOI */ +#if defined(GPIOJ) + else if (GPIOx == GPIOJ) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOJ); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOJ); + } +#endif /* GPIOJ */ +#if defined(GPIOK) + else if (GPIOx == GPIOK) + { + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_GPIOK); + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_GPIOK); + } +#endif /* GPIOK */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Initialize GPIO registers according to the specified parameters in GPIO_InitStruct. + * @param GPIOx GPIO Port + * @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure + * that contains the configuration information for the specified GPIO peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: GPIO registers are initialized according to GPIO_InitStruct content + * - ERROR: Not applicable + */ +ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct) +{ + uint32_t pinpos = 0x00000000U; + uint32_t currentpin = 0x00000000U; + + /* Check the parameters */ + assert_param(IS_GPIO_ALL_INSTANCE(GPIOx)); + assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin)); + assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode)); + assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull)); + + /* ------------------------- Configure the port pins ---------------- */ + /* Initialize pinpos on first pin set */ + pinpos = POSITION_VAL(GPIO_InitStruct->Pin); + + /* Configure the port pins */ + while (((GPIO_InitStruct->Pin) >> pinpos) != 0x00000000U) + { + /* Get current io position */ + currentpin = (GPIO_InitStruct->Pin) & (0x00000001U << pinpos); + + if (currentpin) + { + + if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE)) + { + /* Check Speed mode parameters */ + assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed)); + + /* Speed mode configuration */ + LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed); + + /* Check Output mode parameters */ + assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType)); + + /* Output mode configuration*/ + LL_GPIO_SetPinOutputType(GPIOx, currentpin, GPIO_InitStruct->OutputType); + } + + /* Pull-up Pull down resistor configuration*/ + LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull); + + if (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE) + { + /* Check Alternate parameter */ + assert_param(IS_LL_GPIO_ALTERNATE(GPIO_InitStruct->Alternate)); + + /* Speed mode configuration */ + if (POSITION_VAL(currentpin) < 0x00000008U) + { + LL_GPIO_SetAFPin_0_7(GPIOx, currentpin, GPIO_InitStruct->Alternate); + } + else + { + LL_GPIO_SetAFPin_8_15(GPIOx, currentpin, GPIO_InitStruct->Alternate); + } + } + + /* Pin Mode configuration */ + LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode); + } + pinpos++; + } + + return (SUCCESS); +} + +/** + * @brief Set each @ref LL_GPIO_InitTypeDef field to default value. + * @param GPIO_InitStruct pointer to a @ref LL_GPIO_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ + +void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct) +{ + /* Reset GPIO init structure parameters values */ + GPIO_InitStruct->Pin = LL_GPIO_PIN_ALL; + GPIO_InitStruct->Mode = LL_GPIO_MODE_ANALOG; + GPIO_InitStruct->Speed = LL_GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct->OutputType = LL_GPIO_OUTPUT_PUSHPULL; + GPIO_InitStruct->Pull = LL_GPIO_PULL_NO; + GPIO_InitStruct->Alternate = LL_GPIO_AF_0; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) || defined (GPIOH) || defined (GPIOI) || defined (GPIOJ) || defined (GPIOK) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c new file mode 100644 index 0000000..d25e590 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_i2c.c @@ -0,0 +1,251 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_i2c.c + * @author MCD Application Team + * @brief I2C LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_i2c.h" +#include "stm32f4xx_ll_bus.h" +#include "stm32f4xx_ll_rcc.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (I2C1) || defined (I2C2) || defined (I2C3) + +/** @defgroup I2C_LL I2C + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup I2C_LL_Private_Macros + * @{ + */ + +#define IS_LL_I2C_PERIPHERAL_MODE(__VALUE__) (((__VALUE__) == LL_I2C_MODE_I2C) || \ + ((__VALUE__) == LL_I2C_MODE_SMBUS_HOST) || \ + ((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE) || \ + ((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE_ARP)) + +#define IS_LL_I2C_CLOCK_SPEED(__VALUE__) (((__VALUE__) > 0U) && ((__VALUE__) <= LL_I2C_MAX_SPEED_FAST)) + +#define IS_LL_I2C_DUTY_CYCLE(__VALUE__) (((__VALUE__) == LL_I2C_DUTYCYCLE_2) || \ + ((__VALUE__) == LL_I2C_DUTYCYCLE_16_9)) + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) +#define IS_LL_I2C_ANALOG_FILTER(__VALUE__) (((__VALUE__) == LL_I2C_ANALOGFILTER_ENABLE) || \ + ((__VALUE__) == LL_I2C_ANALOGFILTER_DISABLE)) + +#define IS_LL_I2C_DIGITAL_FILTER(__VALUE__) ((__VALUE__) <= 0x0000000FU) + +#endif +#define IS_LL_I2C_OWN_ADDRESS1(__VALUE__) ((__VALUE__) <= 0x000003FFU) + +#define IS_LL_I2C_TYPE_ACKNOWLEDGE(__VALUE__) (((__VALUE__) == LL_I2C_ACK) || \ + ((__VALUE__) == LL_I2C_NACK)) + +#define IS_LL_I2C_OWN_ADDRSIZE(__VALUE__) (((__VALUE__) == LL_I2C_OWNADDRESS1_7BIT) || \ + ((__VALUE__) == LL_I2C_OWNADDRESS1_10BIT)) +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2C_LL_Exported_Functions + * @{ + */ + +/** @addtogroup I2C_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the I2C registers to their default reset values. + * @param I2Cx I2C Instance. + * @retval An ErrorStatus enumeration value: + * - SUCCESS I2C registers are de-initialized + * - ERROR I2C registers are not de-initialized + */ +uint32_t LL_I2C_DeInit(I2C_TypeDef *I2Cx) +{ + ErrorStatus status = SUCCESS; + + /* Check the I2C Instance I2Cx */ + assert_param(IS_I2C_ALL_INSTANCE(I2Cx)); + + if (I2Cx == I2C1) + { + /* Force reset of I2C clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1); + + /* Release reset of I2C clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1); + } + else if (I2Cx == I2C2) + { + /* Force reset of I2C clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C2); + + /* Release reset of I2C clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C2); + + } +#if defined(I2C3) + else if (I2Cx == I2C3) + { + /* Force reset of I2C clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C3); + + /* Release reset of I2C clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C3); + } +#endif + else + { + status = ERROR; + } + + return status; +} + +/** + * @brief Initialize the I2C registers according to the specified parameters in I2C_InitStruct. + * @param I2Cx I2C Instance. + * @param I2C_InitStruct pointer to a @ref LL_I2C_InitTypeDef structure. + * @retval An ErrorStatus enumeration value: + * - SUCCESS I2C registers are initialized + * - ERROR Not applicable + */ +uint32_t LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct) +{ + LL_RCC_ClocksTypeDef rcc_clocks; + + /* Check the I2C Instance I2Cx */ + assert_param(IS_I2C_ALL_INSTANCE(I2Cx)); + + /* Check the I2C parameters from I2C_InitStruct */ + assert_param(IS_LL_I2C_PERIPHERAL_MODE(I2C_InitStruct->PeripheralMode)); + assert_param(IS_LL_I2C_CLOCK_SPEED(I2C_InitStruct->ClockSpeed)); + assert_param(IS_LL_I2C_DUTY_CYCLE(I2C_InitStruct->DutyCycle)); +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) + assert_param(IS_LL_I2C_ANALOG_FILTER(I2C_InitStruct->AnalogFilter)); + assert_param(IS_LL_I2C_DIGITAL_FILTER(I2C_InitStruct->DigitalFilter)); +#endif + assert_param(IS_LL_I2C_OWN_ADDRESS1(I2C_InitStruct->OwnAddress1)); + assert_param(IS_LL_I2C_TYPE_ACKNOWLEDGE(I2C_InitStruct->TypeAcknowledge)); + assert_param(IS_LL_I2C_OWN_ADDRSIZE(I2C_InitStruct->OwnAddrSize)); + + /* Disable the selected I2Cx Peripheral */ + LL_I2C_Disable(I2Cx); + + /* Retrieve Clock frequencies */ + LL_RCC_GetSystemClocksFreq(&rcc_clocks); + +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) + /*---------------------------- I2Cx FLTR Configuration ----------------------- + * Configure the analog and digital noise filters with parameters : + * - AnalogFilter: I2C_FLTR_ANFOFF bit + * - DigitalFilter: I2C_FLTR_DNF[3:0] bits + */ + LL_I2C_ConfigFilters(I2Cx, I2C_InitStruct->AnalogFilter, I2C_InitStruct->DigitalFilter); + +#endif + /*---------------------------- I2Cx SCL Clock Speed Configuration ------------ + * Configure the SCL speed : + * - ClockSpeed: I2C_CR2_FREQ[5:0], I2C_TRISE_TRISE[5:0], I2C_CCR_FS, + * and I2C_CCR_CCR[11:0] bits + * - DutyCycle: I2C_CCR_DUTY[7:0] bits + */ + LL_I2C_ConfigSpeed(I2Cx, rcc_clocks.PCLK1_Frequency, I2C_InitStruct->ClockSpeed, I2C_InitStruct->DutyCycle); + + /*---------------------------- I2Cx OAR1 Configuration ----------------------- + * Disable, Configure and Enable I2Cx device own address 1 with parameters : + * - OwnAddress1: I2C_OAR1_ADD[9:8], I2C_OAR1_ADD[7:1] and I2C_OAR1_ADD0 bits + * - OwnAddrSize: I2C_OAR1_ADDMODE bit + */ + LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize); + + /*---------------------------- I2Cx MODE Configuration ----------------------- + * Configure I2Cx peripheral mode with parameter : + * - PeripheralMode: I2C_CR1_SMBUS, I2C_CR1_SMBTYPE and I2C_CR1_ENARP bits + */ + LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode); + + /* Enable the selected I2Cx Peripheral */ + LL_I2C_Enable(I2Cx); + + /*---------------------------- I2Cx CR2 Configuration ------------------------ + * Configure the ACKnowledge or Non ACKnowledge condition + * after the address receive match code or next received byte with parameter : + * - TypeAcknowledge: I2C_CR2_NACK bit + */ + LL_I2C_AcknowledgeNextData(I2Cx, I2C_InitStruct->TypeAcknowledge); + + return SUCCESS; +} + +/** + * @brief Set each @ref LL_I2C_InitTypeDef field to default value. + * @param I2C_InitStruct Pointer to a @ref LL_I2C_InitTypeDef structure. + * @retval None + */ +void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct) +{ + /* Set I2C_InitStruct fields to default values */ + I2C_InitStruct->PeripheralMode = LL_I2C_MODE_I2C; + I2C_InitStruct->ClockSpeed = 5000U; + I2C_InitStruct->DutyCycle = LL_I2C_DUTYCYCLE_2; +#if defined(I2C_FLTR_ANOFF)&&defined(I2C_FLTR_DNF) + I2C_InitStruct->AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE; + I2C_InitStruct->DigitalFilter = 0U; +#endif + I2C_InitStruct->OwnAddress1 = 0U; + I2C_InitStruct->TypeAcknowledge = LL_I2C_NACK; + I2C_InitStruct->OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* I2C1 || I2C2 || I2C3 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c new file mode 100644 index 0000000..4ec0840 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_lptim.c @@ -0,0 +1,301 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_lptim.c + * @author MCD Application Team + * @brief LPTIM LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_lptim.h" +#include "stm32f4xx_ll_bus.h" +#include "stm32f4xx_ll_rcc.h" + + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (LPTIM1) + +/** @addtogroup LPTIM_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup LPTIM_LL_Private_Macros + * @{ + */ +#define IS_LL_LPTIM_CLOCK_SOURCE(__VALUE__) (((__VALUE__) == LL_LPTIM_CLK_SOURCE_INTERNAL) \ + || ((__VALUE__) == LL_LPTIM_CLK_SOURCE_EXTERNAL)) + +#define IS_LL_LPTIM_CLOCK_PRESCALER(__VALUE__) (((__VALUE__) == LL_LPTIM_PRESCALER_DIV1) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV2) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV4) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV8) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV16) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV32) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV64) \ + || ((__VALUE__) == LL_LPTIM_PRESCALER_DIV128)) + +#define IS_LL_LPTIM_WAVEFORM(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_PWM) \ + || ((__VALUE__) == LL_LPTIM_OUTPUT_WAVEFORM_SETONCE)) + +#define IS_LL_LPTIM_OUTPUT_POLARITY(__VALUE__) (((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_REGULAR) \ + || ((__VALUE__) == LL_LPTIM_OUTPUT_POLARITY_INVERSE)) +/** + * @} + */ + + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup LPTIM_Private_Functions LPTIM Private Functions + * @{ + */ +/** + * @} + */ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup LPTIM_LL_Exported_Functions + * @{ + */ + +/** @addtogroup LPTIM_LL_EF_Init + * @{ + */ + +/** + * @brief Set LPTIMx registers to their reset values. + * @param LPTIMx LP Timer instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: LPTIMx registers are de-initialized + * - ERROR: invalid LPTIMx instance + */ +ErrorStatus LL_LPTIM_DeInit(LPTIM_TypeDef *LPTIMx) +{ + ErrorStatus result = SUCCESS; + + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(LPTIMx)); + + if (LPTIMx == LPTIM1) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_LPTIM1); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1); + } + else + { + result = ERROR; + } + + return result; +} + +/** + * @brief Set each fields of the LPTIM_InitStruct structure to its default + * value. + * @param LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure + * @retval None + */ +void LL_LPTIM_StructInit(LL_LPTIM_InitTypeDef *LPTIM_InitStruct) +{ + /* Set the default configuration */ + LPTIM_InitStruct->ClockSource = LL_LPTIM_CLK_SOURCE_INTERNAL; + LPTIM_InitStruct->Prescaler = LL_LPTIM_PRESCALER_DIV1; + LPTIM_InitStruct->Waveform = LL_LPTIM_OUTPUT_WAVEFORM_PWM; + LPTIM_InitStruct->Polarity = LL_LPTIM_OUTPUT_POLARITY_REGULAR; +} + +/** + * @brief Configure the LPTIMx peripheral according to the specified parameters. + * @note LL_LPTIM_Init can only be called when the LPTIM instance is disabled. + * @note LPTIMx can be disabled using unitary function @ref LL_LPTIM_Disable(). + * @param LPTIMx LP Timer Instance + * @param LPTIM_InitStruct pointer to a @ref LL_LPTIM_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: LPTIMx instance has been initialized + * - ERROR: LPTIMx instance hasn't been initialized + */ +ErrorStatus LL_LPTIM_Init(LPTIM_TypeDef *LPTIMx, const LL_LPTIM_InitTypeDef *LPTIM_InitStruct) +{ + ErrorStatus result = SUCCESS; + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(LPTIMx)); + assert_param(IS_LL_LPTIM_CLOCK_SOURCE(LPTIM_InitStruct->ClockSource)); + assert_param(IS_LL_LPTIM_CLOCK_PRESCALER(LPTIM_InitStruct->Prescaler)); + assert_param(IS_LL_LPTIM_WAVEFORM(LPTIM_InitStruct->Waveform)); + assert_param(IS_LL_LPTIM_OUTPUT_POLARITY(LPTIM_InitStruct->Polarity)); + + /* The LPTIMx_CFGR register must only be modified when the LPTIM is disabled + (ENABLE bit is reset to 0). + */ + if (LL_LPTIM_IsEnabled(LPTIMx) == 1UL) + { + result = ERROR; + } + else + { + /* Set CKSEL bitfield according to ClockSource value */ + /* Set PRESC bitfield according to Prescaler value */ + /* Set WAVE bitfield according to Waveform value */ + /* Set WAVEPOL bitfield according to Polarity value */ + MODIFY_REG(LPTIMx->CFGR, + (LPTIM_CFGR_CKSEL | LPTIM_CFGR_PRESC | LPTIM_CFGR_WAVE | LPTIM_CFGR_WAVPOL), + LPTIM_InitStruct->ClockSource | \ + LPTIM_InitStruct->Prescaler | \ + LPTIM_InitStruct->Waveform | \ + LPTIM_InitStruct->Polarity); + } + + return result; +} + +/** + * @brief Disable the LPTIM instance + * @rmtoll CR ENABLE LL_LPTIM_Disable + * @param LPTIMx Low-Power Timer instance + * @note The following sequence is required to solve LPTIM disable HW limitation. + * Please check Errata Sheet ES0335 for more details under "MCU may remain + * stuck in LPTIM interrupt when entering Stop mode" section. + * @retval None + */ +void LL_LPTIM_Disable(LPTIM_TypeDef *LPTIMx) +{ + LL_RCC_ClocksTypeDef rcc_clock; + uint32_t tmpclksource = 0; + uint32_t tmpIER; + uint32_t tmpCFGR; + uint32_t tmpCMP; + uint32_t tmpARR; + uint32_t primask_bit; + uint32_t tmpOR; + + /* Check the parameters */ + assert_param(IS_LPTIM_INSTANCE(LPTIMx)); + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1) ; + + /********** Save LPTIM Config *********/ + /* Save LPTIM source clock */ + switch ((uint32_t)LPTIMx) + { + case LPTIM1_BASE: + tmpclksource = LL_RCC_GetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE); + break; + default: + break; + } + + /* Save LPTIM configuration registers */ + tmpIER = LPTIMx->IER; + tmpCFGR = LPTIMx->CFGR; + tmpCMP = LPTIMx->CMP; + tmpARR = LPTIMx->ARR; + tmpOR = LPTIMx->OR; + + /************* Reset LPTIM ************/ + (void)LL_LPTIM_DeInit(LPTIMx); + + /********* Restore LPTIM Config *******/ + LL_RCC_GetSystemClocksFreq(&rcc_clock); + + if ((tmpCMP != 0UL) || (tmpARR != 0UL)) + { + /* Force LPTIM source kernel clock from APB */ + switch ((uint32_t)LPTIMx) + { + case LPTIM1_BASE: + LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1); + break; + default: + break; + } + + if (tmpCMP != 0UL) + { + /* Restore CMP and ARR registers (LPTIM should be enabled first) */ + LPTIMx->CR |= LPTIM_CR_ENABLE; + LPTIMx->CMP = tmpCMP; + + /* Polling on CMP write ok status after above restore operation */ + do + { + rcc_clock.SYSCLK_Frequency--; /* Used for timeout */ + } while (((LL_LPTIM_IsActiveFlag_CMPOK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL)); + + LL_LPTIM_ClearFlag_CMPOK(LPTIMx); + } + + if (tmpARR != 0UL) + { + LPTIMx->CR |= LPTIM_CR_ENABLE; + LPTIMx->ARR = tmpARR; + + LL_RCC_GetSystemClocksFreq(&rcc_clock); + /* Polling on ARR write ok status after above restore operation */ + do + { + rcc_clock.SYSCLK_Frequency--; /* Used for timeout */ + } + while (((LL_LPTIM_IsActiveFlag_ARROK(LPTIMx) != 1UL)) && ((rcc_clock.SYSCLK_Frequency) > 0UL)); + + LL_LPTIM_ClearFlag_ARROK(LPTIMx); + } + + + /* Restore LPTIM source kernel clock */ + LL_RCC_SetLPTIMClockSource(tmpclksource); + } + + /* Restore configuration registers (LPTIM should be disabled first) */ + LPTIMx->CR &= ~(LPTIM_CR_ENABLE); + LPTIMx->IER = tmpIER; + LPTIMx->CFGR = tmpCFGR; + LPTIMx->OR = tmpOR; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* LPTIM1 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c new file mode 100644 index 0000000..0c6f61e --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_pwr.c @@ -0,0 +1,81 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_pwr.c + * @author MCD Application Team + * @brief PWR LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_pwr.h" +#include "stm32f4xx_ll_bus.h" + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(PWR) + +/** @defgroup PWR_LL PWR + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup PWR_LL_Exported_Functions + * @{ + */ + +/** @addtogroup PWR_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the PWR registers to their default reset values. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: PWR registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_PWR_DeInit(void) +{ + /* Force reset of PWR clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_PWR); + + /* Release reset of PWR clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_PWR); + + return SUCCESS; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +#endif /* defined(PWR) */ +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c new file mode 100644 index 0000000..efa3e57 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c @@ -0,0 +1,1660 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_rcc.c + * @author MCD Application Team + * @brief RCC LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_rcc.h" +#ifdef USE_FULL_ASSERT + #include "stm32_assert.h" +#else + #define assert_param(expr) ((void)0U) +#endif +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(RCC) + +/** @addtogroup RCC_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RCC_LL_Private_Macros + * @{ + */ +#if defined(FMPI2C1) +#define IS_LL_RCC_FMPI2C_CLKSOURCE(__VALUE__) ((__VALUE__) == LL_RCC_FMPI2C1_CLKSOURCE) +#endif /* FMPI2C1 */ + +#if defined(LPTIM1) +#define IS_LL_RCC_LPTIM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LPTIM1_CLKSOURCE)) +#endif /* LPTIM1 */ + +#if defined(SAI1) +#if defined(RCC_DCKCFGR_SAI1SRC) +#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_SAI2_CLKSOURCE)) +#elif defined(RCC_DCKCFGR_SAI1ASRC) +#define IS_LL_RCC_SAI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SAI1_A_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_SAI1_B_CLKSOURCE)) +#endif /* RCC_DCKCFGR_SAI1SRC */ +#endif /* SAI1 */ + +#if defined(SDIO) +#define IS_LL_RCC_SDIO_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SDIO_CLKSOURCE)) +#endif /* SDIO */ + +#if defined(RNG) +#define IS_LL_RCC_RNG_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_RNG_CLKSOURCE)) +#endif /* RNG */ + +#if defined(USB_OTG_FS) || defined(USB_OTG_HS) +#define IS_LL_RCC_USB_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USB_CLKSOURCE)) +#endif /* USB_OTG_FS || USB_OTG_HS */ + +#if defined(DFSDM2_Channel0) +#define IS_LL_RCC_DFSDM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_CLKSOURCE)) + +#define IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_AUDIO_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_DFSDM2_AUDIO_CLKSOURCE)) +#elif defined(DFSDM1_Channel0) +#define IS_LL_RCC_DFSDM_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_CLKSOURCE)) + +#define IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DFSDM1_AUDIO_CLKSOURCE)) +#endif /* DFSDM2_Channel0 */ + +#if defined(RCC_DCKCFGR_I2S2SRC) +#define IS_LL_RCC_I2S_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2S1_CLKSOURCE) \ + || ((__VALUE__) == LL_RCC_I2S2_CLKSOURCE)) +#else +#define IS_LL_RCC_I2S_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2S1_CLKSOURCE)) +#endif /* RCC_DCKCFGR_I2S2SRC */ + +#if defined(CEC) +#define IS_LL_RCC_CEC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_CEC_CLKSOURCE)) +#endif /* CEC */ + +#if defined(DSI) +#define IS_LL_RCC_DSI_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_DSI_CLKSOURCE)) +#endif /* DSI */ + +#if defined(LTDC) +#define IS_LL_RCC_LTDC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_LTDC_CLKSOURCE)) +#endif /* LTDC */ + +#if defined(SPDIFRX) +#define IS_LL_RCC_SPDIFRX_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_SPDIFRX1_CLKSOURCE)) +#endif /* SPDIFRX */ +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup RCC_LL_Private_Functions RCC Private functions + * @{ + */ +uint32_t RCC_GetSystemClockFreq(void); +uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency); +uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency); +uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency); +uint32_t RCC_PLL_GetFreqDomain_SYS(uint32_t SYSCLK_Source); +uint32_t RCC_PLL_GetFreqDomain_48M(void); +#if defined(RCC_DCKCFGR_I2SSRC) || defined(RCC_DCKCFGR_I2S1SRC) +uint32_t RCC_PLL_GetFreqDomain_I2S(void); +#endif /* RCC_DCKCFGR_I2SSRC || RCC_DCKCFGR_I2S1SRC */ +#if defined(SPDIFRX) +uint32_t RCC_PLL_GetFreqDomain_SPDIFRX(void); +#endif /* SPDIFRX */ +#if defined(RCC_PLLCFGR_PLLR) +#if defined(SAI1) +uint32_t RCC_PLL_GetFreqDomain_SAI(void); +#endif /* SAI1 */ +#endif /* RCC_PLLCFGR_PLLR */ +#if defined(DSI) +uint32_t RCC_PLL_GetFreqDomain_DSI(void); +#endif /* DSI */ +#if defined(RCC_PLLSAI_SUPPORT) +uint32_t RCC_PLLSAI_GetFreqDomain_SAI(void); +#if defined(RCC_PLLSAICFGR_PLLSAIP) +uint32_t RCC_PLLSAI_GetFreqDomain_48M(void); +#endif /* RCC_PLLSAICFGR_PLLSAIP */ +#if defined(LTDC) +uint32_t RCC_PLLSAI_GetFreqDomain_LTDC(void); +#endif /* LTDC */ +#endif /* RCC_PLLSAI_SUPPORT */ +#if defined(RCC_PLLI2S_SUPPORT) +uint32_t RCC_PLLI2S_GetFreqDomain_I2S(void); +#if defined(RCC_PLLI2SCFGR_PLLI2SQ) && !defined(RCC_DCKCFGR_PLLI2SDIVQ) +uint32_t RCC_PLLI2S_GetFreqDomain_48M(void); +#endif /* RCC_PLLI2SCFGR_PLLI2SQ && !RCC_DCKCFGR_PLLI2SDIVQ */ +#if defined(SAI1) +uint32_t RCC_PLLI2S_GetFreqDomain_SAI(void); +#endif /* SAI1 */ +#if defined(SPDIFRX) +uint32_t RCC_PLLI2S_GetFreqDomain_SPDIFRX(void); +#endif /* SPDIFRX */ +#endif /* RCC_PLLI2S_SUPPORT */ +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RCC_LL_Exported_Functions + * @{ + */ + +/** @addtogroup RCC_LL_EF_Init + * @{ + */ + +/** + * @brief Reset the RCC clock configuration to the default reset state. + * @note The default reset state of the clock configuration is given below: + * - HSI ON and used as system clock source + * - HSE and PLL OFF + * - AHB, APB1 and APB2 prescaler set to 1. + * - CSS, MCO OFF + * - All interrupts disabled + * @note This function doesn't modify the configuration of the + * - Peripheral clocks + * - LSI, LSE and RTC clocks + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RCC registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_RCC_DeInit(void) +{ + __IO uint32_t vl_mask; + + /* Set HSION bit */ + LL_RCC_HSI_Enable(); + + /* Wait for HSI READY bit */ + while(LL_RCC_HSI_IsReady() != 1U) + {} + + /* Reset CFGR register */ + LL_RCC_WriteReg(CFGR, 0x00000000U); + + /* Read CR register */ + vl_mask = LL_RCC_ReadReg(CR); + + /* Reset HSEON, HSEBYP, PLLON, CSSON bits */ + CLEAR_BIT(vl_mask, + (RCC_CR_HSEON | RCC_CR_HSEBYP | RCC_CR_PLLON | RCC_CR_CSSON)); + +#if defined(RCC_PLLSAI_SUPPORT) + /* Reset PLLSAION bit */ + CLEAR_BIT(vl_mask, RCC_CR_PLLSAION); +#endif /* RCC_PLLSAI_SUPPORT */ + +#if defined(RCC_PLLI2S_SUPPORT) + /* Reset PLLI2SON bit */ + CLEAR_BIT(vl_mask, RCC_CR_PLLI2SON); +#endif /* RCC_PLLI2S_SUPPORT */ + + /* Write new value in CR register */ + LL_RCC_WriteReg(CR, vl_mask); + + /* Set HSITRIM bits to the reset value*/ + LL_RCC_HSI_SetCalibTrimming(0x10U); + + /* Wait for PLL READY bit to be reset */ + while(LL_RCC_PLL_IsReady() != 0U) + {} + + /* Reset PLLCFGR register */ + LL_RCC_WriteReg(PLLCFGR, RCC_PLLCFGR_RST_VALUE); + +#if defined(RCC_PLLI2S_SUPPORT) + /* Reset PLLI2SCFGR register */ + LL_RCC_WriteReg(PLLI2SCFGR, RCC_PLLI2SCFGR_RST_VALUE); +#endif /* RCC_PLLI2S_SUPPORT */ + +#if defined(RCC_PLLSAI_SUPPORT) + /* Reset PLLSAICFGR register */ + LL_RCC_WriteReg(PLLSAICFGR, RCC_PLLSAICFGR_RST_VALUE); +#endif /* RCC_PLLSAI_SUPPORT */ + + /* Disable all interrupts */ + CLEAR_BIT(RCC->CIR, RCC_CIR_LSIRDYIE | RCC_CIR_LSERDYIE | RCC_CIR_HSIRDYIE | RCC_CIR_HSERDYIE | RCC_CIR_PLLRDYIE); + +#if defined(RCC_CIR_PLLI2SRDYIE) + CLEAR_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYIE); +#endif /* RCC_CIR_PLLI2SRDYIE */ + +#if defined(RCC_CIR_PLLSAIRDYIE) + CLEAR_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYIE); +#endif /* RCC_CIR_PLLSAIRDYIE */ + + /* Clear all interrupt flags */ + SET_BIT(RCC->CIR, RCC_CIR_LSIRDYC | RCC_CIR_LSERDYC | RCC_CIR_HSIRDYC | RCC_CIR_HSERDYC | RCC_CIR_PLLRDYC | RCC_CIR_CSSC); + +#if defined(RCC_CIR_PLLI2SRDYC) + SET_BIT(RCC->CIR, RCC_CIR_PLLI2SRDYC); +#endif /* RCC_CIR_PLLI2SRDYC */ + +#if defined(RCC_CIR_PLLSAIRDYC) + SET_BIT(RCC->CIR, RCC_CIR_PLLSAIRDYC); +#endif /* RCC_CIR_PLLSAIRDYC */ + + /* Clear LSION bit */ + CLEAR_BIT(RCC->CSR, RCC_CSR_LSION); + + /* Reset all CSR flags */ + SET_BIT(RCC->CSR, RCC_CSR_RMVF); + + return SUCCESS; +} + +/** + * @} + */ + +/** @addtogroup RCC_LL_EF_Get_Freq + * @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks + * and different peripheral clocks available on the device. + * @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(**) + * @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(***) + * @note If SYSCLK source is PLL, function returns values based on HSE_VALUE(***) + * or HSI_VALUE(**) multiplied/divided by the PLL factors. + * @note (**) HSI_VALUE is a constant defined in this file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * @note (***) HSE_VALUE is a constant defined in this file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * @note The result of this function could be incorrect when using fractional + * value for HSE crystal. + * @note This function can be used by the user application to compute the + * baud-rate for the communication peripherals or configure other parameters. + * @{ + */ + +/** + * @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks + * @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function + * must be called to update structure fields. Otherwise, any + * configuration based on this function will be incorrect. + * @param RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies + * @retval None + */ +void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks) +{ + /* Get SYSCLK frequency */ + RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq(); + + /* HCLK clock frequency */ + RCC_Clocks->HCLK_Frequency = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency); + + /* PCLK1 clock frequency */ + RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency); + + /* PCLK2 clock frequency */ + RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK_Frequency); +} + +#if defined(FMPI2C1) +/** + * @brief Return FMPI2Cx clock frequency + * @param FMPI2CxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_FMPI2C1_CLKSOURCE + * @retval FMPI2C clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that HSI oscillator is not ready + */ +uint32_t LL_RCC_GetFMPI2CClockFreq(uint32_t FMPI2CxSource) +{ + uint32_t FMPI2C_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_FMPI2C_CLKSOURCE(FMPI2CxSource)); + + if (FMPI2CxSource == LL_RCC_FMPI2C1_CLKSOURCE) + { + /* FMPI2C1 CLK clock frequency */ + switch (LL_RCC_GetFMPI2CClockSource(FMPI2CxSource)) + { + case LL_RCC_FMPI2C1_CLKSOURCE_SYSCLK: /* FMPI2C1 Clock is System Clock */ + FMPI2C_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_FMPI2C1_CLKSOURCE_HSI: /* FMPI2C1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady()) + { + FMPI2C_frequency = HSI_VALUE; + } + break; + + case LL_RCC_FMPI2C1_CLKSOURCE_PCLK1: /* FMPI2C1 Clock is PCLK1 */ + default: + FMPI2C_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + } + } + + return FMPI2C_frequency; +} +#endif /* FMPI2C1 */ + +/** + * @brief Return I2Sx clock frequency + * @param I2SxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_I2S1_CLKSOURCE + * @arg @ref LL_RCC_I2S2_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval I2S clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetI2SClockFreq(uint32_t I2SxSource) +{ + uint32_t i2s_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_I2S_CLKSOURCE(I2SxSource)); + + if (I2SxSource == LL_RCC_I2S1_CLKSOURCE) + { + /* I2S1 CLK clock frequency */ + switch (LL_RCC_GetI2SClockSource(I2SxSource)) + { +#if defined(RCC_PLLI2S_SUPPORT) + case LL_RCC_I2S1_CLKSOURCE_PLLI2S: /* I2S1 Clock is PLLI2S */ + if (LL_RCC_PLLI2S_IsReady()) + { + i2s_frequency = RCC_PLLI2S_GetFreqDomain_I2S(); + } + break; +#endif /* RCC_PLLI2S_SUPPORT */ + +#if defined(RCC_DCKCFGR_I2SSRC) || defined(RCC_DCKCFGR_I2S1SRC) + case LL_RCC_I2S1_CLKSOURCE_PLL: /* I2S1 Clock is PLL */ + if (LL_RCC_PLL_IsReady()) + { + i2s_frequency = RCC_PLL_GetFreqDomain_I2S(); + } + break; + + case LL_RCC_I2S1_CLKSOURCE_PLLSRC: /* I2S1 Clock is PLL Main source */ + switch (LL_RCC_PLL_GetMainSource()) + { + case LL_RCC_PLLSOURCE_HSE: /* I2S1 Clock is HSE Osc. */ + if (LL_RCC_HSE_IsReady()) + { + i2s_frequency = HSE_VALUE; + } + break; + + case LL_RCC_PLLSOURCE_HSI: /* I2S1 Clock is HSI Osc. */ + default: + if (LL_RCC_HSI_IsReady()) + { + i2s_frequency = HSI_VALUE; + } + break; + } + break; +#endif /* RCC_DCKCFGR_I2SSRC || RCC_DCKCFGR_I2S1SRC */ + + case LL_RCC_I2S1_CLKSOURCE_PIN: /* I2S1 Clock is External clock */ + default: + i2s_frequency = EXTERNAL_CLOCK_VALUE; + break; + } + } +#if defined(RCC_DCKCFGR_I2S2SRC) + else + { + /* I2S2 CLK clock frequency */ + switch (LL_RCC_GetI2SClockSource(I2SxSource)) + { + case LL_RCC_I2S2_CLKSOURCE_PLLI2S: /* I2S2 Clock is PLLI2S */ + if (LL_RCC_PLLI2S_IsReady()) + { + i2s_frequency = RCC_PLLI2S_GetFreqDomain_I2S(); + } + break; + + case LL_RCC_I2S2_CLKSOURCE_PLL: /* I2S2 Clock is PLL */ + if (LL_RCC_PLL_IsReady()) + { + i2s_frequency = RCC_PLL_GetFreqDomain_I2S(); + } + break; + + case LL_RCC_I2S2_CLKSOURCE_PLLSRC: /* I2S2 Clock is PLL Main source */ + switch (LL_RCC_PLL_GetMainSource()) + { + case LL_RCC_PLLSOURCE_HSE: /* I2S2 Clock is HSE Osc. */ + if (LL_RCC_HSE_IsReady()) + { + i2s_frequency = HSE_VALUE; + } + break; + + case LL_RCC_PLLSOURCE_HSI: /* I2S2 Clock is HSI Osc. */ + default: + if (LL_RCC_HSI_IsReady()) + { + i2s_frequency = HSI_VALUE; + } + break; + } + break; + + case LL_RCC_I2S2_CLKSOURCE_PIN: /* I2S2 Clock is External clock */ + default: + i2s_frequency = EXTERNAL_CLOCK_VALUE; + break; + } + } +#endif /* RCC_DCKCFGR_I2S2SRC */ + + return i2s_frequency; +} + +#if defined(LPTIM1) +/** + * @brief Return LPTIMx clock frequency + * @param LPTIMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LPTIM1_CLKSOURCE + * @retval LPTIM clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI, LSI or LSE) is not ready + */ +uint32_t LL_RCC_GetLPTIMClockFreq(uint32_t LPTIMxSource) +{ + uint32_t lptim_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_LPTIM_CLKSOURCE(LPTIMxSource)); + + if (LPTIMxSource == LL_RCC_LPTIM1_CLKSOURCE) + { + /* LPTIM1CLK clock frequency */ + switch (LL_RCC_GetLPTIMClockSource(LPTIMxSource)) + { + case LL_RCC_LPTIM1_CLKSOURCE_LSI: /* LPTIM1 Clock is LSI Osc. */ + if (LL_RCC_LSI_IsReady()) + { + lptim_frequency = LSI_VALUE; + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_HSI: /* LPTIM1 Clock is HSI Osc. */ + if (LL_RCC_HSI_IsReady()) + { + lptim_frequency = HSI_VALUE; + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_LSE: /* LPTIM1 Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady()) + { + lptim_frequency = LSE_VALUE; + } + break; + + case LL_RCC_LPTIM1_CLKSOURCE_PCLK1: /* LPTIM1 Clock is PCLK1 */ + default: + lptim_frequency = RCC_GetPCLK1ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + } + } + + return lptim_frequency; +} +#endif /* LPTIM1 */ + +#if defined(SAI1) +/** + * @brief Return SAIx clock frequency + * @param SAIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SAI1_CLKSOURCE (*) + * @arg @ref LL_RCC_SAI2_CLKSOURCE (*) + * @arg @ref LL_RCC_SAI1_A_CLKSOURCE (*) + * @arg @ref LL_RCC_SAI1_B_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval SAI clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetSAIClockFreq(uint32_t SAIxSource) +{ + uint32_t sai_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SAI_CLKSOURCE(SAIxSource)); + +#if defined(RCC_DCKCFGR_SAI1SRC) + if ((SAIxSource == LL_RCC_SAI1_CLKSOURCE) || (SAIxSource == LL_RCC_SAI2_CLKSOURCE)) + { + /* SAI1CLK clock frequency */ + switch (LL_RCC_GetSAIClockSource(SAIxSource)) + { + case LL_RCC_SAI1_CLKSOURCE_PLLSAI: /* PLLSAI clock used as SAI1 clock source */ + case LL_RCC_SAI2_CLKSOURCE_PLLSAI: /* PLLSAI clock used as SAI2 clock source */ + if (LL_RCC_PLLSAI_IsReady()) + { + sai_frequency = RCC_PLLSAI_GetFreqDomain_SAI(); + } + break; + + case LL_RCC_SAI1_CLKSOURCE_PLLI2S: /* PLLI2S clock used as SAI1 clock source */ + case LL_RCC_SAI2_CLKSOURCE_PLLI2S: /* PLLI2S clock used as SAI2 clock source */ + if (LL_RCC_PLLI2S_IsReady()) + { + sai_frequency = RCC_PLLI2S_GetFreqDomain_SAI(); + } + break; + + case LL_RCC_SAI1_CLKSOURCE_PLL: /* PLL clock used as SAI1 clock source */ + case LL_RCC_SAI2_CLKSOURCE_PLL: /* PLL clock used as SAI2 clock source */ + if (LL_RCC_PLL_IsReady()) + { + sai_frequency = RCC_PLL_GetFreqDomain_SAI(); + } + break; + + case LL_RCC_SAI2_CLKSOURCE_PLLSRC: + switch (LL_RCC_PLL_GetMainSource()) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE clock used as SAI2 clock source */ + if (LL_RCC_HSE_IsReady()) + { + sai_frequency = HSE_VALUE; + } + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI clock used as SAI2 clock source */ + default: + if (LL_RCC_HSI_IsReady()) + { + sai_frequency = HSI_VALUE; + } + break; + } + break; + + case LL_RCC_SAI1_CLKSOURCE_PIN: /* External input clock used as SAI1 clock source */ + default: + sai_frequency = EXTERNAL_CLOCK_VALUE; + break; + } + } +#endif /* RCC_DCKCFGR_SAI1SRC */ +#if defined(RCC_DCKCFGR_SAI1ASRC) + if ((SAIxSource == LL_RCC_SAI1_A_CLKSOURCE) || (SAIxSource == LL_RCC_SAI1_B_CLKSOURCE)) + { + /* SAI1CLK clock frequency */ + switch (LL_RCC_GetSAIClockSource(SAIxSource)) + { +#if defined(RCC_PLLSAI_SUPPORT) + case LL_RCC_SAI1_A_CLKSOURCE_PLLSAI: /* PLLSAI clock used as SAI1 Block A clock source */ + case LL_RCC_SAI1_B_CLKSOURCE_PLLSAI: /* PLLSAI clock used as SAI1 Block B clock source */ + if (LL_RCC_PLLSAI_IsReady()) + { + sai_frequency = RCC_PLLSAI_GetFreqDomain_SAI(); + } + break; +#endif /* RCC_PLLSAI_SUPPORT */ + + case LL_RCC_SAI1_A_CLKSOURCE_PLLI2S: /* PLLI2S clock used as SAI1 Block A clock source */ + case LL_RCC_SAI1_B_CLKSOURCE_PLLI2S: /* PLLI2S clock used as SAI1 Block B clock source */ + if (LL_RCC_PLLI2S_IsReady()) + { + sai_frequency = RCC_PLLI2S_GetFreqDomain_SAI(); + } + break; + +#if defined(RCC_SAI1A_PLLSOURCE_SUPPORT) + case LL_RCC_SAI1_A_CLKSOURCE_PLL: /* PLL clock used as SAI1 Block A clock source */ + case LL_RCC_SAI1_B_CLKSOURCE_PLL: /* PLL clock used as SAI1 Block B clock source */ + if (LL_RCC_PLL_IsReady()) + { + sai_frequency = RCC_PLL_GetFreqDomain_SAI(); + } + break; + + case LL_RCC_SAI1_A_CLKSOURCE_PLLSRC: + case LL_RCC_SAI1_B_CLKSOURCE_PLLSRC: + switch (LL_RCC_PLL_GetMainSource()) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE clock used as SAI1 Block A or B clock source */ + if (LL_RCC_HSE_IsReady()) + { + sai_frequency = HSE_VALUE; + } + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI clock used as SAI1 Block A or B clock source */ + default: + if (LL_RCC_HSI_IsReady()) + { + sai_frequency = HSI_VALUE; + } + break; + } + break; +#endif /* RCC_SAI1A_PLLSOURCE_SUPPORT */ + + case LL_RCC_SAI1_A_CLKSOURCE_PIN: /* External input clock used as SAI1 Block A clock source */ + case LL_RCC_SAI1_B_CLKSOURCE_PIN: /* External input clock used as SAI1 Block B clock source */ + default: + sai_frequency = EXTERNAL_CLOCK_VALUE; + break; + } + } +#endif /* RCC_DCKCFGR_SAI1ASRC */ + + return sai_frequency; +} +#endif /* SAI1 */ + +#if defined(SDIO) +/** + * @brief Return SDIOx clock frequency + * @param SDIOxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SDIO_CLKSOURCE + * @retval SDIO clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetSDIOClockFreq(uint32_t SDIOxSource) +{ + uint32_t SDIO_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SDIO_CLKSOURCE(SDIOxSource)); + + if (SDIOxSource == LL_RCC_SDIO_CLKSOURCE) + { +#if defined(RCC_DCKCFGR_SDIOSEL) || defined(RCC_DCKCFGR2_SDIOSEL) + /* SDIOCLK clock frequency */ + switch (LL_RCC_GetSDIOClockSource(SDIOxSource)) + { + case LL_RCC_SDIO_CLKSOURCE_PLL48CLK: /* PLL48M clock used as SDIO clock source */ + switch (LL_RCC_GetCK48MClockSource(LL_RCC_CK48M_CLKSOURCE)) + { + case LL_RCC_CK48M_CLKSOURCE_PLL: /* PLL clock used as 48Mhz domain clock */ + if (LL_RCC_PLL_IsReady()) + { + SDIO_frequency = RCC_PLL_GetFreqDomain_48M(); + } + break; + +#if defined(RCC_PLLSAI_SUPPORT) + case LL_RCC_CK48M_CLKSOURCE_PLLSAI: /* PLLSAI clock used as 48Mhz domain clock */ + default: + if (LL_RCC_PLLSAI_IsReady()) + { + SDIO_frequency = RCC_PLLSAI_GetFreqDomain_48M(); + } + break; +#endif /* RCC_PLLSAI_SUPPORT */ + +#if defined(RCC_PLLI2SCFGR_PLLI2SQ) && !defined(RCC_DCKCFGR_PLLI2SDIVQ) + case LL_RCC_CK48M_CLKSOURCE_PLLI2S: /* PLLI2S clock used as 48Mhz domain clock */ + default: + if (LL_RCC_PLLI2S_IsReady()) + { + SDIO_frequency = RCC_PLLI2S_GetFreqDomain_48M(); + } + break; +#endif /* RCC_PLLI2SCFGR_PLLI2SQ && !RCC_DCKCFGR_PLLI2SDIVQ */ + } + break; + + case LL_RCC_SDIO_CLKSOURCE_SYSCLK: /* PLL clock used as SDIO clock source */ + default: + SDIO_frequency = RCC_GetSystemClockFreq(); + break; + } +#else + /* PLL clock used as 48Mhz domain clock */ + if (LL_RCC_PLL_IsReady()) + { + SDIO_frequency = RCC_PLL_GetFreqDomain_48M(); + } +#endif /* RCC_DCKCFGR_SDIOSEL || RCC_DCKCFGR2_SDIOSEL */ + } + + return SDIO_frequency; +} +#endif /* SDIO */ + +#if defined(RNG) +/** + * @brief Return RNGx clock frequency + * @param RNGxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_RNG_CLKSOURCE + * @retval RNG clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetRNGClockFreq(uint32_t RNGxSource) +{ + uint32_t rng_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_RNG_CLKSOURCE(RNGxSource)); + +#if defined(RCC_DCKCFGR_CK48MSEL) || defined(RCC_DCKCFGR2_CK48MSEL) + /* RNGCLK clock frequency */ + switch (LL_RCC_GetRNGClockSource(RNGxSource)) + { +#if defined(RCC_PLLI2SCFGR_PLLI2SQ) && !defined(RCC_DCKCFGR_PLLI2SDIVQ) + case LL_RCC_RNG_CLKSOURCE_PLLI2S: /* PLLI2S clock used as RNG clock source */ + if (LL_RCC_PLLI2S_IsReady()) + { + rng_frequency = RCC_PLLI2S_GetFreqDomain_48M(); + } + break; +#endif /* RCC_PLLI2SCFGR_PLLI2SQ && !RCC_DCKCFGR_PLLI2SDIVQ */ + +#if defined(RCC_PLLSAI_SUPPORT) + case LL_RCC_RNG_CLKSOURCE_PLLSAI: /* PLLSAI clock used as RNG clock source */ + if (LL_RCC_PLLSAI_IsReady()) + { + rng_frequency = RCC_PLLSAI_GetFreqDomain_48M(); + } + break; +#endif /* RCC_PLLSAI_SUPPORT */ + + case LL_RCC_RNG_CLKSOURCE_PLL: /* PLL clock used as RNG clock source */ + default: + if (LL_RCC_PLL_IsReady()) + { + rng_frequency = RCC_PLL_GetFreqDomain_48M(); + } + break; + } +#else + /* PLL clock used as RNG clock source */ + if (LL_RCC_PLL_IsReady()) + { + rng_frequency = RCC_PLL_GetFreqDomain_48M(); + } +#endif /* RCC_DCKCFGR_CK48MSEL || RCC_DCKCFGR2_CK48MSEL */ + + return rng_frequency; +} +#endif /* RNG */ + +#if defined(CEC) +/** + * @brief Return CEC clock frequency + * @param CECxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_CEC_CLKSOURCE + * @retval CEC clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI or LSE) is not ready + */ +uint32_t LL_RCC_GetCECClockFreq(uint32_t CECxSource) +{ + uint32_t cec_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_CEC_CLKSOURCE(CECxSource)); + + /* CECCLK clock frequency */ + switch (LL_RCC_GetCECClockSource(CECxSource)) + { + case LL_RCC_CEC_CLKSOURCE_LSE: /* CEC Clock is LSE Osc. */ + if (LL_RCC_LSE_IsReady()) + { + cec_frequency = LSE_VALUE; + } + break; + + case LL_RCC_CEC_CLKSOURCE_HSI_DIV488: /* CEC Clock is HSI Osc. */ + default: + if (LL_RCC_HSI_IsReady()) + { + cec_frequency = HSI_VALUE/488U; + } + break; + } + + return cec_frequency; +} +#endif /* CEC */ + +#if defined(USB_OTG_FS) || defined(USB_OTG_HS) +/** + * @brief Return USBx clock frequency + * @param USBxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_USB_CLKSOURCE + * @retval USB clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource) +{ + uint32_t usb_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_USB_CLKSOURCE(USBxSource)); + +#if defined(RCC_DCKCFGR_CK48MSEL) || defined(RCC_DCKCFGR2_CK48MSEL) + /* USBCLK clock frequency */ + switch (LL_RCC_GetUSBClockSource(USBxSource)) + { +#if defined(RCC_PLLI2SCFGR_PLLI2SQ) && !defined(RCC_DCKCFGR_PLLI2SDIVQ) + case LL_RCC_USB_CLKSOURCE_PLLI2S: /* PLLI2S clock used as USB clock source */ + if (LL_RCC_PLLI2S_IsReady()) + { + usb_frequency = RCC_PLLI2S_GetFreqDomain_48M(); + } + break; + +#endif /* RCC_PLLI2SCFGR_PLLI2SQ && !RCC_DCKCFGR_PLLI2SDIVQ */ + +#if defined(RCC_PLLSAI_SUPPORT) + case LL_RCC_USB_CLKSOURCE_PLLSAI: /* PLLSAI clock used as USB clock source */ + if (LL_RCC_PLLSAI_IsReady()) + { + usb_frequency = RCC_PLLSAI_GetFreqDomain_48M(); + } + break; +#endif /* RCC_PLLSAI_SUPPORT */ + + case LL_RCC_USB_CLKSOURCE_PLL: /* PLL clock used as USB clock source */ + default: + if (LL_RCC_PLL_IsReady()) + { + usb_frequency = RCC_PLL_GetFreqDomain_48M(); + } + break; + } +#else + /* PLL clock used as USB clock source */ + if (LL_RCC_PLL_IsReady()) + { + usb_frequency = RCC_PLL_GetFreqDomain_48M(); + } +#endif /* RCC_DCKCFGR_CK48MSEL || RCC_DCKCFGR2_CK48MSEL */ + + return usb_frequency; +} +#endif /* USB_OTG_FS || USB_OTG_HS */ + +#if defined(DFSDM1_Channel0) +/** + * @brief Return DFSDMx clock frequency + * @param DFSDMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_CLKSOURCE + * @arg @ref LL_RCC_DFSDM2_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval DFSDM clock frequency (in Hz) + */ +uint32_t LL_RCC_GetDFSDMClockFreq(uint32_t DFSDMxSource) +{ + uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_DFSDM_CLKSOURCE(DFSDMxSource)); + + if (DFSDMxSource == LL_RCC_DFSDM1_CLKSOURCE) + { + /* DFSDM1CLK clock frequency */ + switch (LL_RCC_GetDFSDMClockSource(DFSDMxSource)) + { + case LL_RCC_DFSDM1_CLKSOURCE_SYSCLK: /* DFSDM1 Clock is SYSCLK */ + dfsdm_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_DFSDM1_CLKSOURCE_PCLK2: /* DFSDM1 Clock is PCLK2 */ + default: + dfsdm_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + } + } +#if defined(DFSDM2_Channel0) + else + { + /* DFSDM2CLK clock frequency */ + switch (LL_RCC_GetDFSDMClockSource(DFSDMxSource)) + { + case LL_RCC_DFSDM2_CLKSOURCE_SYSCLK: /* DFSDM2 Clock is SYSCLK */ + dfsdm_frequency = RCC_GetSystemClockFreq(); + break; + + case LL_RCC_DFSDM2_CLKSOURCE_PCLK2: /* DFSDM2 Clock is PCLK2 */ + default: + dfsdm_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq())); + break; + } + } +#endif /* DFSDM2_Channel0 */ + + return dfsdm_frequency; +} + +/** + * @brief Return DFSDMx Audio clock frequency + * @param DFSDMxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_DFSDM1_AUDIO_CLKSOURCE + * @arg @ref LL_RCC_DFSDM2_AUDIO_CLKSOURCE (*) + * + * (*) value not defined in all devices. + * @retval DFSDM clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetDFSDMAudioClockFreq(uint32_t DFSDMxSource) +{ + uint32_t dfsdm_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_DFSDM_AUDIO_CLKSOURCE(DFSDMxSource)); + + if (DFSDMxSource == LL_RCC_DFSDM1_AUDIO_CLKSOURCE) + { + /* DFSDM1CLK clock frequency */ + switch (LL_RCC_GetDFSDMAudioClockSource(DFSDMxSource)) + { + case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_I2S1: /* I2S1 clock used as DFSDM1 clock */ + dfsdm_frequency = LL_RCC_GetI2SClockFreq(LL_RCC_I2S1_CLKSOURCE); + break; + + case LL_RCC_DFSDM1_AUDIO_CLKSOURCE_I2S2: /* I2S2 clock used as DFSDM1 clock */ + default: + dfsdm_frequency = LL_RCC_GetI2SClockFreq(LL_RCC_I2S2_CLKSOURCE); + break; + } + } +#if defined(DFSDM2_Channel0) + else + { + /* DFSDM2CLK clock frequency */ + switch (LL_RCC_GetDFSDMAudioClockSource(DFSDMxSource)) + { + case LL_RCC_DFSDM2_AUDIO_CLKSOURCE_I2S1: /* I2S1 clock used as DFSDM2 clock */ + dfsdm_frequency = LL_RCC_GetI2SClockFreq(LL_RCC_I2S1_CLKSOURCE); + break; + + case LL_RCC_DFSDM2_AUDIO_CLKSOURCE_I2S2: /* I2S2 clock used as DFSDM2 clock */ + default: + dfsdm_frequency = LL_RCC_GetI2SClockFreq(LL_RCC_I2S2_CLKSOURCE); + break; + } + } +#endif /* DFSDM2_Channel0 */ + + return dfsdm_frequency; +} +#endif /* DFSDM1_Channel0 */ + +#if defined(DSI) +/** + * @brief Return DSI clock frequency + * @param DSIxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_DSI_CLKSOURCE + * @retval DSI clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + * - @ref LL_RCC_PERIPH_FREQUENCY_NA indicates that external clock is used + */ +uint32_t LL_RCC_GetDSIClockFreq(uint32_t DSIxSource) +{ + uint32_t dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_DSI_CLKSOURCE(DSIxSource)); + + /* DSICLK clock frequency */ + switch (LL_RCC_GetDSIClockSource(DSIxSource)) + { + case LL_RCC_DSI_CLKSOURCE_PLL: /* DSI Clock is PLL Osc. */ + if (LL_RCC_PLL_IsReady()) + { + dsi_frequency = RCC_PLL_GetFreqDomain_DSI(); + } + break; + + case LL_RCC_DSI_CLKSOURCE_PHY: /* DSI Clock is DSI physical clock. */ + default: + dsi_frequency = LL_RCC_PERIPH_FREQUENCY_NA; + break; + } + + return dsi_frequency; +} +#endif /* DSI */ + +#if defined(LTDC) +/** + * @brief Return LTDC clock frequency + * @param LTDCxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_LTDC_CLKSOURCE + * @retval LTDC clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator PLLSAI is not ready + */ +uint32_t LL_RCC_GetLTDCClockFreq(uint32_t LTDCxSource) +{ + uint32_t ltdc_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_LTDC_CLKSOURCE(LTDCxSource)); + + if (LL_RCC_PLLSAI_IsReady()) + { + ltdc_frequency = RCC_PLLSAI_GetFreqDomain_LTDC(); + } + + return ltdc_frequency; +} +#endif /* LTDC */ + +#if defined(SPDIFRX) +/** + * @brief Return SPDIFRX clock frequency + * @param SPDIFRXxSource This parameter can be one of the following values: + * @arg @ref LL_RCC_SPDIFRX1_CLKSOURCE + * @retval SPDIFRX clock frequency (in Hz) + * - @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator is not ready + */ +uint32_t LL_RCC_GetSPDIFRXClockFreq(uint32_t SPDIFRXxSource) +{ + uint32_t spdifrx_frequency = LL_RCC_PERIPH_FREQUENCY_NO; + + /* Check parameter */ + assert_param(IS_LL_RCC_SPDIFRX_CLKSOURCE(SPDIFRXxSource)); + + /* SPDIFRX1CLK clock frequency */ + switch (LL_RCC_GetSPDIFRXClockSource(SPDIFRXxSource)) + { + case LL_RCC_SPDIFRX1_CLKSOURCE_PLLI2S: /* SPDIFRX Clock is PLLI2S Osc. */ + if (LL_RCC_PLLI2S_IsReady()) + { + spdifrx_frequency = RCC_PLLI2S_GetFreqDomain_SPDIFRX(); + } + break; + + case LL_RCC_SPDIFRX1_CLKSOURCE_PLL: /* SPDIFRX Clock is PLL Osc. */ + default: + if (LL_RCC_PLL_IsReady()) + { + spdifrx_frequency = RCC_PLL_GetFreqDomain_SPDIFRX(); + } + break; + } + + return spdifrx_frequency; +} +#endif /* SPDIFRX */ + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup RCC_LL_Private_Functions + * @{ + */ + +/** + * @brief Return SYSTEM clock frequency + * @retval SYSTEM clock frequency (in Hz) + */ +uint32_t RCC_GetSystemClockFreq(void) +{ + uint32_t frequency = 0U; + + /* Get SYSCLK source -------------------------------------------------------*/ + switch (LL_RCC_GetSysClkSource()) + { + case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: /* HSI used as system clock source */ + frequency = HSI_VALUE; + break; + + case LL_RCC_SYS_CLKSOURCE_STATUS_HSE: /* HSE used as system clock source */ + frequency = HSE_VALUE; + break; + + case LL_RCC_SYS_CLKSOURCE_STATUS_PLL: /* PLL used as system clock source */ + frequency = RCC_PLL_GetFreqDomain_SYS(LL_RCC_SYS_CLKSOURCE_STATUS_PLL); + break; + +#if defined(RCC_PLLR_SYSCLK_SUPPORT) + case LL_RCC_SYS_CLKSOURCE_STATUS_PLLR: /* PLLR used as system clock source */ + frequency = RCC_PLL_GetFreqDomain_SYS(LL_RCC_SYS_CLKSOURCE_STATUS_PLLR); + break; +#endif /* RCC_PLLR_SYSCLK_SUPPORT */ + + default: + frequency = HSI_VALUE; + break; + } + + return frequency; +} + +/** + * @brief Return HCLK clock frequency + * @param SYSCLK_Frequency SYSCLK clock frequency + * @retval HCLK clock frequency (in Hz) + */ +uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency) +{ + /* HCLK clock frequency */ + return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler()); +} + +/** + * @brief Return PCLK1 clock frequency + * @param HCLK_Frequency HCLK clock frequency + * @retval PCLK1 clock frequency (in Hz) + */ +uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency) +{ + /* PCLK1 clock frequency */ + return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler()); +} + +/** + * @brief Return PCLK2 clock frequency + * @param HCLK_Frequency HCLK clock frequency + * @retval PCLK2 clock frequency (in Hz) + */ +uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency) +{ + /* PCLK2 clock frequency */ + return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler()); +} + +/** + * @brief Return PLL clock frequency used for system domain + * @param SYSCLK_Source System clock source + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_SYS(uint32_t SYSCLK_Source) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U, plloutputfreq = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SYSCLK = PLL_VCO / (PLLP or PLLR) + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = HSI_VALUE; + break; + } + + if (SYSCLK_Source == LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + plloutputfreq = __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetP()); + } +#if defined(RCC_PLLR_SYSCLK_SUPPORT) + else + { + plloutputfreq = __LL_RCC_CALC_PLLRCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); + } +#endif /* RCC_PLLR_SYSCLK_SUPPORT */ + + return plloutputfreq; +} + +/** + * @brief Return PLL clock frequency used for 48 MHz domain + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_48M(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM ) * PLLN + 48M Domain clock = PLL_VCO / PLLQ + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLCLK_48M_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetQ()); +} + +#if defined(DSI) +/** + * @brief Return PLL clock frequency used for DSI clock + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_DSI(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + DSICLK = PLL_VCO / PLLR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLCLK_DSI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); +} +#endif /* DSI */ + +#if defined(RCC_DCKCFGR_I2SSRC) || defined(RCC_DCKCFGR_I2S1SRC) +/** + * @brief Return PLL clock frequency used for I2S clock + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_I2S(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + I2SCLK = PLL_VCO / PLLR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLCLK_I2S_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); +} +#endif /* RCC_DCKCFGR_I2SSRC || RCC_DCKCFGR_I2S1SRC */ + +#if defined(SPDIFRX) +/** + * @brief Return PLL clock frequency used for SPDIFRX clock + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_SPDIFRX(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SPDIFRXCLK = PLL_VCO / PLLR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLCLK_SPDIFRX_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); +} +#endif /* SPDIFRX */ + +#if defined(RCC_PLLCFGR_PLLR) +#if defined(SAI1) +/** + * @brief Return PLL clock frequency used for SAI clock + * @retval PLL clock frequency (in Hz) + */ +uint32_t RCC_PLL_GetFreqDomain_SAI(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U, plloutputfreq = 0U; + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN + SAICLK = (PLL_VCO / PLLR) / PLLDIVR + or + SAICLK = PLL_VCO / PLLR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */ + pllinputfreq = HSE_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLL clock source */ + default: + pllinputfreq = HSI_VALUE; + break; + } + +#if defined(RCC_DCKCFGR_PLLDIVR) + plloutputfreq = __LL_RCC_CALC_PLLCLK_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR(), LL_RCC_PLL_GetDIVR()); +#else + plloutputfreq = __LL_RCC_CALC_PLLCLK_SAI_FREQ(pllinputfreq, LL_RCC_PLL_GetDivider(), + LL_RCC_PLL_GetN(), LL_RCC_PLL_GetR()); +#endif /* RCC_DCKCFGR_PLLDIVR */ + + return plloutputfreq; +} +#endif /* SAI1 */ +#endif /* RCC_PLLCFGR_PLLR */ + +#if defined(RCC_PLLSAI_SUPPORT) +/** + * @brief Return PLLSAI clock frequency used for SAI domain + * @retval PLLSAI clock frequency (in Hz) + */ +uint32_t RCC_PLLSAI_GetFreqDomain_SAI(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLLSAI_VCO = (HSE_VALUE or HSI_VALUE / PLLSAIM) * PLLSAIN + SAI domain clock = (PLLSAI_VCO / PLLSAIQ) / PLLSAIDIVQ + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLSAI_SAI_FREQ(pllinputfreq, LL_RCC_PLLSAI_GetDivider(), + LL_RCC_PLLSAI_GetN(), LL_RCC_PLLSAI_GetQ(), LL_RCC_PLLSAI_GetDIVQ()); +} + +#if defined(RCC_PLLSAICFGR_PLLSAIP) +/** + * @brief Return PLLSAI clock frequency used for 48Mhz domain + * @retval PLLSAI clock frequency (in Hz) + */ +uint32_t RCC_PLLSAI_GetFreqDomain_48M(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLLSAI_VCO = (HSE_VALUE or HSI_VALUE / PLLSAIM) * PLLSAIN + 48M Domain clock = PLLSAI_VCO / PLLSAIP + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLSAI_48M_FREQ(pllinputfreq, LL_RCC_PLLSAI_GetDivider(), + LL_RCC_PLLSAI_GetN(), LL_RCC_PLLSAI_GetP()); +} +#endif /* RCC_PLLSAICFGR_PLLSAIP */ + +#if defined(LTDC) +/** + * @brief Return PLLSAI clock frequency used for LTDC domain + * @retval PLLSAI clock frequency (in Hz) + */ +uint32_t RCC_PLLSAI_GetFreqDomain_LTDC(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLLSAI_VCO = (HSE_VALUE or HSI_VALUE / PLLSAIM) * PLLSAIN + LTDC Domain clock = (PLLSAI_VCO / PLLSAIR) / PLLSAIDIVR + */ + pllsource = LL_RCC_PLL_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLSAI clock source */ + pllinputfreq = HSI_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLSAI clock source */ + pllinputfreq = HSE_VALUE; + break; + + default: + pllinputfreq = HSI_VALUE; + break; + } + return __LL_RCC_CALC_PLLSAI_LTDC_FREQ(pllinputfreq, LL_RCC_PLLSAI_GetDivider(), + LL_RCC_PLLSAI_GetN(), LL_RCC_PLLSAI_GetR(), LL_RCC_PLLSAI_GetDIVR()); +} +#endif /* LTDC */ +#endif /* RCC_PLLSAI_SUPPORT */ + +#if defined(RCC_PLLI2S_SUPPORT) +#if defined(SAI1) +/** + * @brief Return PLLI2S clock frequency used for SAI domains + * @retval PLLI2S clock frequency (in Hz) + */ +uint32_t RCC_PLLI2S_GetFreqDomain_SAI(void) +{ + uint32_t plli2sinputfreq = 0U, plli2ssource = 0U, plli2soutputfreq = 0U; + + /* PLLI2S_VCO = (HSE_VALUE or HSI_VALUE / PLLI2SM) * PLLI2SN + SAI domain clock = (PLLI2S_VCO / PLLI2SQ) / PLLI2SDIVQ + or + SAI domain clock = (PLLI2S_VCO / PLLI2SR) / PLLI2SDIVR + */ + plli2ssource = LL_RCC_PLLI2S_GetMainSource(); + + switch (plli2ssource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLI2S clock source */ + plli2sinputfreq = HSE_VALUE; + break; + +#if defined(RCC_PLLI2SCFGR_PLLI2SSRC) + case LL_RCC_PLLI2SSOURCE_PIN: /* External pin input clock used as PLLI2S clock source */ + plli2sinputfreq = EXTERNAL_CLOCK_VALUE; + break; +#endif /* RCC_PLLI2SCFGR_PLLI2SSRC */ + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLI2S clock source */ + default: + plli2sinputfreq = HSI_VALUE; + break; + } + +#if defined(RCC_DCKCFGR_PLLI2SDIVQ) + plli2soutputfreq = __LL_RCC_CALC_PLLI2S_SAI_FREQ(plli2sinputfreq, LL_RCC_PLLI2S_GetDivider(), + LL_RCC_PLLI2S_GetN(), LL_RCC_PLLI2S_GetQ(), LL_RCC_PLLI2S_GetDIVQ()); +#else + plli2soutputfreq = __LL_RCC_CALC_PLLI2S_SAI_FREQ(plli2sinputfreq, LL_RCC_PLLI2S_GetDivider(), + LL_RCC_PLLI2S_GetN(), LL_RCC_PLLI2S_GetR(), LL_RCC_PLLI2S_GetDIVR()); +#endif /* RCC_DCKCFGR_PLLI2SDIVQ */ + + return plli2soutputfreq; +} +#endif /* SAI1 */ + +#if defined(SPDIFRX) +/** + * @brief Return PLLI2S clock frequency used for SPDIFRX domain + * @retval PLLI2S clock frequency (in Hz) + */ +uint32_t RCC_PLLI2S_GetFreqDomain_SPDIFRX(void) +{ + uint32_t pllinputfreq = 0U, pllsource = 0U; + + /* PLLI2S_VCO = (HSE_VALUE or HSI_VALUE / PLLI2SM) * PLLI2SN + SPDIFRX Domain clock = PLLI2S_VCO / PLLI2SP + */ + pllsource = LL_RCC_PLLI2S_GetMainSource(); + + switch (pllsource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLI2S clock source */ + pllinputfreq = HSE_VALUE; + break; + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLI2S clock source */ + default: + pllinputfreq = HSI_VALUE; + break; + } + + return __LL_RCC_CALC_PLLI2S_SPDIFRX_FREQ(pllinputfreq, LL_RCC_PLLI2S_GetDivider(), + LL_RCC_PLLI2S_GetN(), LL_RCC_PLLI2S_GetP()); +} +#endif /* SPDIFRX */ + +/** + * @brief Return PLLI2S clock frequency used for I2S domain + * @retval PLLI2S clock frequency (in Hz) + */ +uint32_t RCC_PLLI2S_GetFreqDomain_I2S(void) +{ + uint32_t plli2sinputfreq = 0U, plli2ssource = 0U, plli2soutputfreq = 0U; + + /* PLLI2S_VCO = (HSE_VALUE or HSI_VALUE / PLLI2SM) * PLLI2SN + I2S Domain clock = PLLI2S_VCO / PLLI2SR + */ + plli2ssource = LL_RCC_PLLI2S_GetMainSource(); + + switch (plli2ssource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLI2S clock source */ + plli2sinputfreq = HSE_VALUE; + break; + +#if defined(RCC_PLLI2SCFGR_PLLI2SSRC) + case LL_RCC_PLLI2SSOURCE_PIN: /* External pin input clock used as PLLI2S clock source */ + plli2sinputfreq = EXTERNAL_CLOCK_VALUE; + break; +#endif /* RCC_PLLI2SCFGR_PLLI2SSRC */ + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLI2S clock source */ + default: + plli2sinputfreq = HSI_VALUE; + break; + } + + plli2soutputfreq = __LL_RCC_CALC_PLLI2S_I2S_FREQ(plli2sinputfreq, LL_RCC_PLLI2S_GetDivider(), + LL_RCC_PLLI2S_GetN(), LL_RCC_PLLI2S_GetR()); + + return plli2soutputfreq; +} + +#if defined(RCC_PLLI2SCFGR_PLLI2SQ) && !defined(RCC_DCKCFGR_PLLI2SDIVQ) +/** + * @brief Return PLLI2S clock frequency used for 48Mhz domain + * @retval PLLI2S clock frequency (in Hz) + */ +uint32_t RCC_PLLI2S_GetFreqDomain_48M(void) +{ + uint32_t plli2sinputfreq = 0U, plli2ssource = 0U, plli2soutputfreq = 0U; + + /* PLL48M_VCO = (HSE_VALUE or HSI_VALUE / PLLI2SM) * PLLI2SN + 48M Domain clock = PLLI2S_VCO / PLLI2SQ + */ + plli2ssource = LL_RCC_PLLI2S_GetMainSource(); + + switch (plli2ssource) + { + case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLLI2S clock source */ + plli2sinputfreq = HSE_VALUE; + break; + +#if defined(RCC_PLLI2SCFGR_PLLI2SSRC) + case LL_RCC_PLLI2SSOURCE_PIN: /* External pin input clock used as PLLI2S clock source */ + plli2sinputfreq = EXTERNAL_CLOCK_VALUE; + break; +#endif /* RCC_PLLI2SCFGR_PLLI2SSRC */ + + case LL_RCC_PLLSOURCE_HSI: /* HSI used as PLLI2S clock source */ + default: + plli2sinputfreq = HSI_VALUE; + break; + } + + plli2soutputfreq = __LL_RCC_CALC_PLLI2S_48M_FREQ(plli2sinputfreq, LL_RCC_PLLI2S_GetDivider(), + LL_RCC_PLLI2S_GetN(), LL_RCC_PLLI2S_GetQ()); + + return plli2soutputfreq; +} +#endif /* RCC_PLLI2SCFGR_PLLI2SQ && !RCC_DCKCFGR_PLLI2SDIVQ */ +#endif /* RCC_PLLI2S_SUPPORT */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RCC) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c new file mode 100644 index 0000000..333d63c --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rng.c @@ -0,0 +1,111 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_rng.c + * @author MCD Application Team + * @brief RNG LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_rng.h" +#include "stm32f4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (RNG) + +/** @addtogroup RNG_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RNG_LL_Exported_Functions + * @{ + */ + +/** @addtogroup RNG_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize RNG registers (Registers restored to their default values). + * @param RNGx RNG Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RNG registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_RNG_DeInit(RNG_TypeDef *RNGx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_RNG_ALL_INSTANCE(RNGx)); + if (RNGx == RNG) + { +#if !defined(RCC_AHB2_SUPPORT) + /* Enable RNG reset state */ + LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_RNG); + + /* Release RNG from reset state */ + LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_RNG); +#else + /* Enable RNG reset state */ + LL_AHB2_GRP1_ForceReset(LL_AHB2_GRP1_PERIPH_RNG); + + /* Release RNG from reset state */ + LL_AHB2_GRP1_ReleaseReset(LL_AHB2_GRP1_PERIPH_RNG); +#endif /* !RCC_AHB2_SUPPORT */ + } + else + { + status = ERROR; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* RNG */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c new file mode 100644 index 0000000..f3ee3ce --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rtc.c @@ -0,0 +1,838 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_rtc.c + * @author MCD Application Team + * @brief RTC LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_rtc.h" +#include "stm32f4xx_ll_cortex.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined(RTC) + +/** @addtogroup RTC_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup RTC_LL_Private_Constants + * @{ + */ +/* Default values used for prescaler */ +#define RTC_ASYNCH_PRESC_DEFAULT 0x0000007FU +#define RTC_SYNCH_PRESC_DEFAULT 0x000000FFU + +/* Values used for timeout */ +#define RTC_INITMODE_TIMEOUT 1000U /* 1s when tick set to 1ms */ +#define RTC_SYNCHRO_TIMEOUT 1000U /* 1s when tick set to 1ms */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup RTC_LL_Private_Macros + * @{ + */ + +#define IS_LL_RTC_HOURFORMAT(__VALUE__) (((__VALUE__) == LL_RTC_HOURFORMAT_24HOUR) \ + || ((__VALUE__) == LL_RTC_HOURFORMAT_AMPM)) + +#define IS_LL_RTC_ASYNCH_PREDIV(__VALUE__) ((__VALUE__) <= 0x7FU) + +#define IS_LL_RTC_SYNCH_PREDIV(__VALUE__) ((__VALUE__) <= 0x7FFFU) + +#define IS_LL_RTC_FORMAT(__VALUE__) (((__VALUE__) == LL_RTC_FORMAT_BIN) \ + || ((__VALUE__) == LL_RTC_FORMAT_BCD)) + +#define IS_LL_RTC_TIME_FORMAT(__VALUE__) (((__VALUE__) == LL_RTC_TIME_FORMAT_AM_OR_24) \ + || ((__VALUE__) == LL_RTC_TIME_FORMAT_PM)) + +#define IS_LL_RTC_HOUR12(__HOUR__) (((__HOUR__) > 0U) && ((__HOUR__) <= 12U)) +#define IS_LL_RTC_HOUR24(__HOUR__) ((__HOUR__) <= 23U) +#define IS_LL_RTC_MINUTES(__MINUTES__) ((__MINUTES__) <= 59U) +#define IS_LL_RTC_SECONDS(__SECONDS__) ((__SECONDS__) <= 59U) + +#define IS_LL_RTC_WEEKDAY(__VALUE__) (((__VALUE__) == LL_RTC_WEEKDAY_MONDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_TUESDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_WEDNESDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_THURSDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_FRIDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_SATURDAY) \ + || ((__VALUE__) == LL_RTC_WEEKDAY_SUNDAY)) + +#define IS_LL_RTC_DAY(__DAY__) (((__DAY__) >= 1U) && ((__DAY__) <= 31U)) + +#define IS_LL_RTC_MONTH(__MONTH__) (((__MONTH__) >= 1U) && ((__MONTH__) <= 12U)) + +#define IS_LL_RTC_YEAR(__YEAR__) ((__YEAR__) <= 99U) + +#define IS_LL_RTC_ALMA_MASK(__VALUE__) (((__VALUE__) == LL_RTC_ALMA_MASK_NONE) \ + || ((__VALUE__) == LL_RTC_ALMA_MASK_DATEWEEKDAY) \ + || ((__VALUE__) == LL_RTC_ALMA_MASK_HOURS) \ + || ((__VALUE__) == LL_RTC_ALMA_MASK_MINUTES) \ + || ((__VALUE__) == LL_RTC_ALMA_MASK_SECONDS) \ + || ((__VALUE__) == LL_RTC_ALMA_MASK_ALL)) + +#define IS_LL_RTC_ALMB_MASK(__VALUE__) (((__VALUE__) == LL_RTC_ALMB_MASK_NONE) \ + || ((__VALUE__) == LL_RTC_ALMB_MASK_DATEWEEKDAY) \ + || ((__VALUE__) == LL_RTC_ALMB_MASK_HOURS) \ + || ((__VALUE__) == LL_RTC_ALMB_MASK_MINUTES) \ + || ((__VALUE__) == LL_RTC_ALMB_MASK_SECONDS) \ + || ((__VALUE__) == LL_RTC_ALMB_MASK_ALL)) + +#define IS_LL_RTC_ALMA_DATE_WEEKDAY_SEL(__SEL__) (((__SEL__) == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE) || \ + ((__SEL__) == LL_RTC_ALMA_DATEWEEKDAYSEL_WEEKDAY)) + +#define IS_LL_RTC_ALMB_DATE_WEEKDAY_SEL(__SEL__) (((__SEL__) == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE) || \ + ((__SEL__) == LL_RTC_ALMB_DATEWEEKDAYSEL_WEEKDAY)) + +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup RTC_LL_Exported_Functions + * @{ + */ + +/** @addtogroup RTC_LL_EF_Init + * @{ + */ + +/** + * @brief De-Initializes the RTC registers to their default reset values. + * @note This function does not reset the RTC Clock source and RTC Backup Data + * registers. + * @param RTCx RTC Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are de-initialized + * - ERROR: RTC registers are not de-initialized + */ +ErrorStatus LL_RTC_DeInit(RTC_TypeDef *RTCx) +{ + ErrorStatus status = ERROR; + + /* Check the parameter */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Set Initialization mode */ + if (LL_RTC_EnterInitMode(RTCx) != ERROR) + { + /* Reset TR, DR and CR registers */ + LL_RTC_WriteReg(RTCx, TR, 0x00000000U); + LL_RTC_WriteReg(RTCx, WUTR, RTC_WUTR_WUT); + LL_RTC_WriteReg(RTCx, DR, (RTC_DR_WDU_0 | RTC_DR_MU_0 | RTC_DR_DU_0)); + + /* Reset All CR bits except CR[2:0] */ + LL_RTC_WriteReg(RTCx, CR, (LL_RTC_ReadReg(RTCx, CR) & RTC_CR_WUCKSEL)); + + LL_RTC_WriteReg(RTCx, PRER, (RTC_PRER_PREDIV_A | RTC_SYNCH_PRESC_DEFAULT)); + LL_RTC_WriteReg(RTCx, ALRMAR, 0x00000000U); + LL_RTC_WriteReg(RTCx, ALRMBR, 0x00000000U); + LL_RTC_WriteReg(RTCx, CALR, 0x00000000U); + LL_RTC_WriteReg(RTCx, SHIFTR, 0x00000000U); + LL_RTC_WriteReg(RTCx, ALRMASSR, 0x00000000U); + LL_RTC_WriteReg(RTCx, ALRMBSSR, 0x00000000U); + + /* Reset ISR register and exit initialization mode */ + LL_RTC_WriteReg(RTCx, ISR, 0x00000000U); + + /* Reset Tamper and alternate functions configuration register */ + LL_RTC_WriteReg(RTCx, TAFCR, 0x00000000U); + + /* Wait till the RTC RSF flag is set */ + status = LL_RTC_WaitForSynchro(RTCx); + } + + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return status; +} + +/** + * @brief Initializes the RTC registers according to the specified parameters + * in RTC_InitStruct. + * @param RTCx RTC Instance + * @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure that contains + * the configuration information for the RTC peripheral. + * @note The RTC Prescaler register is write protected and can be written in + * initialization mode only. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are initialized + * - ERROR: RTC registers are not initialized + */ +ErrorStatus LL_RTC_Init(RTC_TypeDef *RTCx, LL_RTC_InitTypeDef *RTC_InitStruct) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + assert_param(IS_LL_RTC_HOURFORMAT(RTC_InitStruct->HourFormat)); + assert_param(IS_LL_RTC_ASYNCH_PREDIV(RTC_InitStruct->AsynchPrescaler)); + assert_param(IS_LL_RTC_SYNCH_PREDIV(RTC_InitStruct->SynchPrescaler)); + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Set Initialization mode */ + if (LL_RTC_EnterInitMode(RTCx) != ERROR) + { + /* Set Hour Format */ + LL_RTC_SetHourFormat(RTCx, RTC_InitStruct->HourFormat); + + /* Configure Synchronous and Asynchronous prescaler factor */ + LL_RTC_SetSynchPrescaler(RTCx, RTC_InitStruct->SynchPrescaler); + LL_RTC_SetAsynchPrescaler(RTCx, RTC_InitStruct->AsynchPrescaler); + + /* Exit Initialization mode */ + LL_RTC_DisableInitMode(RTCx); + + status = SUCCESS; + } + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return status; +} + +/** + * @brief Set each @ref LL_RTC_InitTypeDef field to default value. + * @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure which will be initialized. + * @retval None + */ +void LL_RTC_StructInit(LL_RTC_InitTypeDef *RTC_InitStruct) +{ + /* Set RTC_InitStruct fields to default values */ + RTC_InitStruct->HourFormat = LL_RTC_HOURFORMAT_24HOUR; + RTC_InitStruct->AsynchPrescaler = RTC_ASYNCH_PRESC_DEFAULT; + RTC_InitStruct->SynchPrescaler = RTC_SYNCH_PRESC_DEFAULT; +} + +/** + * @brief Set the RTC current time. + * @param RTCx RTC Instance + * @param RTC_Format This parameter can be one of the following values: + * @arg @ref LL_RTC_FORMAT_BIN + * @arg @ref LL_RTC_FORMAT_BCD + * @param RTC_TimeStruct pointer to a RTC_TimeTypeDef structure that contains + * the time configuration information for the RTC. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC Time register is configured + * - ERROR: RTC Time register is not configured + */ +ErrorStatus LL_RTC_TIME_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_TimeTypeDef *RTC_TimeStruct) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + assert_param(IS_LL_RTC_FORMAT(RTC_Format)); + + if (RTC_Format == LL_RTC_FORMAT_BIN) + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(RTC_TimeStruct->Hours)); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_TimeStruct->TimeFormat)); + } + else + { + RTC_TimeStruct->TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(RTC_TimeStruct->Hours)); + } + assert_param(IS_LL_RTC_MINUTES(RTC_TimeStruct->Minutes)); + assert_param(IS_LL_RTC_SECONDS(RTC_TimeStruct->Seconds)); + } + else + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours))); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_TimeStruct->TimeFormat)); + } + else + { + RTC_TimeStruct->TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours))); + } + assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Minutes))); + assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Seconds))); + } + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Set Initialization mode */ + if (LL_RTC_EnterInitMode(RTCx) != ERROR) + { + /* Check the input parameters format */ + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_TIME_Config(RTCx, RTC_TimeStruct->TimeFormat, RTC_TimeStruct->Hours, + RTC_TimeStruct->Minutes, RTC_TimeStruct->Seconds); + } + else + { + LL_RTC_TIME_Config(RTCx, RTC_TimeStruct->TimeFormat, __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Hours), + __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Minutes), + __LL_RTC_CONVERT_BIN2BCD(RTC_TimeStruct->Seconds)); + } + + /* Exit Initialization mode */ + LL_RTC_DisableInitMode(RTCx); + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if (LL_RTC_IsShadowRegBypassEnabled(RTCx) == 0U) + { + status = LL_RTC_WaitForSynchro(RTCx); + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return status; +} + +/** + * @brief Set each @ref LL_RTC_TimeTypeDef field to default value (Time = 00h:00min:00sec). + * @param RTC_TimeStruct pointer to a @ref LL_RTC_TimeTypeDef structure which will be initialized. + * @retval None + */ +void LL_RTC_TIME_StructInit(LL_RTC_TimeTypeDef *RTC_TimeStruct) +{ + /* Time = 00h:00min:00sec */ + RTC_TimeStruct->TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24; + RTC_TimeStruct->Hours = 0U; + RTC_TimeStruct->Minutes = 0U; + RTC_TimeStruct->Seconds = 0U; +} + +/** + * @brief Set the RTC current date. + * @param RTCx RTC Instance + * @param RTC_Format This parameter can be one of the following values: + * @arg @ref LL_RTC_FORMAT_BIN + * @arg @ref LL_RTC_FORMAT_BCD + * @param RTC_DateStruct pointer to a RTC_DateTypeDef structure that contains + * the date configuration information for the RTC. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC Day register is configured + * - ERROR: RTC Day register is not configured + */ +ErrorStatus LL_RTC_DATE_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_DateTypeDef *RTC_DateStruct) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + assert_param(IS_LL_RTC_FORMAT(RTC_Format)); + + if ((RTC_Format == LL_RTC_FORMAT_BIN) && ((RTC_DateStruct->Month & 0x10U) == 0x10U)) + { + RTC_DateStruct->Month = (uint8_t)(RTC_DateStruct->Month & (uint8_t)~(0x10U)) + 0x0AU; + } + if (RTC_Format == LL_RTC_FORMAT_BIN) + { + assert_param(IS_LL_RTC_YEAR(RTC_DateStruct->Year)); + assert_param(IS_LL_RTC_MONTH(RTC_DateStruct->Month)); + assert_param(IS_LL_RTC_DAY(RTC_DateStruct->Day)); + } + else + { + assert_param(IS_LL_RTC_YEAR(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Year))); + assert_param(IS_LL_RTC_MONTH(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Month))); + assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_DateStruct->Day))); + } + assert_param(IS_LL_RTC_WEEKDAY(RTC_DateStruct->WeekDay)); + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Set Initialization mode */ + if (LL_RTC_EnterInitMode(RTCx) != ERROR) + { + /* Check the input parameters format */ + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_DATE_Config(RTCx, RTC_DateStruct->WeekDay, RTC_DateStruct->Day, RTC_DateStruct->Month, RTC_DateStruct->Year); + } + else + { + LL_RTC_DATE_Config(RTCx, RTC_DateStruct->WeekDay, __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Day), + __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Month), __LL_RTC_CONVERT_BIN2BCD(RTC_DateStruct->Year)); + } + + /* Exit Initialization mode */ + LL_RTC_DisableInitMode(RTCx); + + /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ + if (LL_RTC_IsShadowRegBypassEnabled(RTCx) == 0U) + { + status = LL_RTC_WaitForSynchro(RTCx); + } + else + { + status = SUCCESS; + } + } + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return status; +} + +/** + * @brief Set each @ref LL_RTC_DateTypeDef field to default value (date = Monday, January 01 xx00) + * @param RTC_DateStruct pointer to a @ref LL_RTC_DateTypeDef structure which will be initialized. + * @retval None + */ +void LL_RTC_DATE_StructInit(LL_RTC_DateTypeDef *RTC_DateStruct) +{ + /* Monday, January 01 xx00 */ + RTC_DateStruct->WeekDay = LL_RTC_WEEKDAY_MONDAY; + RTC_DateStruct->Day = 1U; + RTC_DateStruct->Month = LL_RTC_MONTH_JANUARY; + RTC_DateStruct->Year = 0U; +} + +/** + * @brief Set the RTC Alarm A. + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (Use @ref LL_RTC_ALMA_Disable function). + * @param RTCx RTC Instance + * @param RTC_Format This parameter can be one of the following values: + * @arg @ref LL_RTC_FORMAT_BIN + * @arg @ref LL_RTC_FORMAT_BCD + * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure that + * contains the alarm configuration parameters. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ALARMA registers are configured + * - ERROR: ALARMA registers are not configured + */ +ErrorStatus LL_RTC_ALMA_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct) +{ + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + assert_param(IS_LL_RTC_FORMAT(RTC_Format)); + assert_param(IS_LL_RTC_ALMA_MASK(RTC_AlarmStruct->AlarmMask)); + assert_param(IS_LL_RTC_ALMA_DATE_WEEKDAY_SEL(RTC_AlarmStruct->AlarmDateWeekDaySel)); + + if (RTC_Format == LL_RTC_FORMAT_BIN) + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(RTC_AlarmStruct->AlarmTime.Hours)); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat)); + } + else + { + RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(RTC_AlarmStruct->AlarmTime.Hours)); + } + assert_param(IS_LL_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes)); + assert_param(IS_LL_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds)); + + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE) + { + assert_param(IS_LL_RTC_DAY(RTC_AlarmStruct->AlarmDateWeekDay)); + } + else + { + assert_param(IS_LL_RTC_WEEKDAY(RTC_AlarmStruct->AlarmDateWeekDay)); + } + } + else + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours))); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat)); + } + else + { + RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours))); + } + + assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes))); + assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds))); + + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE) + { + assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay))); + } + else + { + assert_param(IS_LL_RTC_WEEKDAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay))); + } + } + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Select weekday selection */ + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMA_DATEWEEKDAYSEL_DATE) + { + /* Set the date for ALARM */ + LL_RTC_ALMA_DisableWeekday(RTCx); + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_ALMA_SetDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay); + } + else + { + LL_RTC_ALMA_SetDay(RTCx, __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmDateWeekDay)); + } + } + else + { + /* Set the week day for ALARM */ + LL_RTC_ALMA_EnableWeekday(RTCx); + LL_RTC_ALMA_SetWeekDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay); + } + + /* Configure the Alarm register */ + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_ALMA_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, RTC_AlarmStruct->AlarmTime.Hours, + RTC_AlarmStruct->AlarmTime.Minutes, RTC_AlarmStruct->AlarmTime.Seconds); + } + else + { + LL_RTC_ALMA_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Hours), + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Minutes), + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Seconds)); + } + /* Set ALARM mask */ + LL_RTC_ALMA_SetMask(RTCx, RTC_AlarmStruct->AlarmMask); + + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return SUCCESS; +} + +/** + * @brief Set the RTC Alarm B. + * @note The Alarm register can only be written when the corresponding Alarm + * is disabled (@ref LL_RTC_ALMB_Disable function). + * @param RTCx RTC Instance + * @param RTC_Format This parameter can be one of the following values: + * @arg @ref LL_RTC_FORMAT_BIN + * @arg @ref LL_RTC_FORMAT_BCD + * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure that + * contains the alarm configuration parameters. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: ALARMB registers are configured + * - ERROR: ALARMB registers are not configured + */ +ErrorStatus LL_RTC_ALMB_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct) +{ + /* Check the parameters */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + assert_param(IS_LL_RTC_FORMAT(RTC_Format)); + assert_param(IS_LL_RTC_ALMB_MASK(RTC_AlarmStruct->AlarmMask)); + assert_param(IS_LL_RTC_ALMB_DATE_WEEKDAY_SEL(RTC_AlarmStruct->AlarmDateWeekDaySel)); + + if (RTC_Format == LL_RTC_FORMAT_BIN) + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(RTC_AlarmStruct->AlarmTime.Hours)); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat)); + } + else + { + RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(RTC_AlarmStruct->AlarmTime.Hours)); + } + assert_param(IS_LL_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes)); + assert_param(IS_LL_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds)); + + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE) + { + assert_param(IS_LL_RTC_DAY(RTC_AlarmStruct->AlarmDateWeekDay)); + } + else + { + assert_param(IS_LL_RTC_WEEKDAY(RTC_AlarmStruct->AlarmDateWeekDay)); + } + } + else + { + if (LL_RTC_GetHourFormat(RTCx) != LL_RTC_HOURFORMAT_24HOUR) + { + assert_param(IS_LL_RTC_HOUR12(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours))); + assert_param(IS_LL_RTC_TIME_FORMAT(RTC_AlarmStruct->AlarmTime.TimeFormat)); + } + else + { + RTC_AlarmStruct->AlarmTime.TimeFormat = 0x00U; + assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours))); + } + + assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes))); + assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds))); + + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE) + { + assert_param(IS_LL_RTC_DAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay))); + } + else + { + assert_param(IS_LL_RTC_WEEKDAY(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmDateWeekDay))); + } + } + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTCx); + + /* Select weekday selection */ + if (RTC_AlarmStruct->AlarmDateWeekDaySel == LL_RTC_ALMB_DATEWEEKDAYSEL_DATE) + { + /* Set the date for ALARM */ + LL_RTC_ALMB_DisableWeekday(RTCx); + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_ALMB_SetDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay); + } + else + { + LL_RTC_ALMB_SetDay(RTCx, __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmDateWeekDay)); + } + } + else + { + /* Set the week day for ALARM */ + LL_RTC_ALMB_EnableWeekday(RTCx); + LL_RTC_ALMB_SetWeekDay(RTCx, RTC_AlarmStruct->AlarmDateWeekDay); + } + + /* Configure the Alarm register */ + if (RTC_Format != LL_RTC_FORMAT_BIN) + { + LL_RTC_ALMB_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, RTC_AlarmStruct->AlarmTime.Hours, + RTC_AlarmStruct->AlarmTime.Minutes, RTC_AlarmStruct->AlarmTime.Seconds); + } + else + { + LL_RTC_ALMB_ConfigTime(RTCx, RTC_AlarmStruct->AlarmTime.TimeFormat, + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Hours), + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Minutes), + __LL_RTC_CONVERT_BIN2BCD(RTC_AlarmStruct->AlarmTime.Seconds)); + } + /* Set ALARM mask */ + LL_RTC_ALMB_SetMask(RTCx, RTC_AlarmStruct->AlarmMask); + + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTCx); + + return SUCCESS; +} + +/** + * @brief Set each @ref LL_RTC_AlarmTypeDef of ALARMA field to default value (Time = 00h:00mn:00sec / + * Day = 1st day of the month/Mask = all fields are masked). + * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure which will be initialized. + * @retval None + */ +void LL_RTC_ALMA_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct) +{ + /* Alarm Time Settings : Time = 00h:00mn:00sec */ + RTC_AlarmStruct->AlarmTime.TimeFormat = LL_RTC_ALMA_TIME_FORMAT_AM; + RTC_AlarmStruct->AlarmTime.Hours = 0U; + RTC_AlarmStruct->AlarmTime.Minutes = 0U; + RTC_AlarmStruct->AlarmTime.Seconds = 0U; + + /* Alarm Day Settings : Day = 1st day of the month */ + RTC_AlarmStruct->AlarmDateWeekDaySel = LL_RTC_ALMA_DATEWEEKDAYSEL_DATE; + RTC_AlarmStruct->AlarmDateWeekDay = 1U; + + /* Alarm Masks Settings : Mask = all fields are not masked */ + RTC_AlarmStruct->AlarmMask = LL_RTC_ALMA_MASK_NONE; +} + +/** + * @brief Set each @ref LL_RTC_AlarmTypeDef of ALARMA field to default value (Time = 00h:00mn:00sec / + * Day = 1st day of the month/Mask = all fields are masked). + * @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure which will be initialized. + * @retval None + */ +void LL_RTC_ALMB_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct) +{ + /* Alarm Time Settings : Time = 00h:00mn:00sec */ + RTC_AlarmStruct->AlarmTime.TimeFormat = LL_RTC_ALMB_TIME_FORMAT_AM; + RTC_AlarmStruct->AlarmTime.Hours = 0U; + RTC_AlarmStruct->AlarmTime.Minutes = 0U; + RTC_AlarmStruct->AlarmTime.Seconds = 0U; + + /* Alarm Day Settings : Day = 1st day of the month */ + RTC_AlarmStruct->AlarmDateWeekDaySel = LL_RTC_ALMB_DATEWEEKDAYSEL_DATE; + RTC_AlarmStruct->AlarmDateWeekDay = 1U; + + /* Alarm Masks Settings : Mask = all fields are not masked */ + RTC_AlarmStruct->AlarmMask = LL_RTC_ALMB_MASK_NONE; +} + +/** + * @brief Enters the RTC Initialization mode. + * @note The RTC Initialization mode is write protected, use the + * @ref LL_RTC_DisableWriteProtection before calling this function. + * @param RTCx RTC Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC is in Init mode + * - ERROR: RTC is not in Init mode + */ +ErrorStatus LL_RTC_EnterInitMode(RTC_TypeDef *RTCx) +{ + __IO uint32_t timeout = RTC_INITMODE_TIMEOUT; + ErrorStatus status = SUCCESS; + uint32_t tmp = 0U; + + /* Check the parameter */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + + /* Check if the Initialization mode is set */ + if (LL_RTC_IsActiveFlag_INIT(RTCx) == 0U) + { + /* Set the Initialization mode */ + LL_RTC_EnableInitMode(RTCx); + + /* Wait till RTC is in INIT state and if Time out is reached exit */ + tmp = LL_RTC_IsActiveFlag_INIT(RTCx); + while ((timeout != 0U) && (tmp != 1U)) + { + if (LL_SYSTICK_IsActiveCounterFlag() == 1U) + { + timeout --; + } + tmp = LL_RTC_IsActiveFlag_INIT(RTCx); + if (timeout == 0U) + { + status = ERROR; + } + } + } + return status; +} + +/** + * @brief Exit the RTC Initialization mode. + * @note When the initialization sequence is complete, the calendar restarts + * counting after 4 RTCCLK cycles. + * @note The RTC Initialization mode is write protected, use the + * @ref LL_RTC_DisableWriteProtection before calling this function. + * @param RTCx RTC Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC exited from in Init mode + * - ERROR: Not applicable + */ +ErrorStatus LL_RTC_ExitInitMode(RTC_TypeDef *RTCx) +{ + /* Check the parameter */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + + /* Disable initialization mode */ + LL_RTC_DisableInitMode(RTCx); + + return SUCCESS; +} + +/** + * @brief Waits until the RTC Time and Day registers (RTC_TR and RTC_DR) are + * synchronized with RTC APB clock. + * @note The RTC Resynchronization mode is write protected, use the + * @ref LL_RTC_DisableWriteProtection before calling this function. + * @note To read the calendar through the shadow registers after calendar + * initialization, calendar update or after wakeup from low power modes + * the software must first clear the RSF flag. + * The software must then wait until it is set again before reading + * the calendar, which means that the calendar registers have been + * correctly copied into the RTC_TR and RTC_DR shadow registers. + * @param RTCx RTC Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: RTC registers are synchronised + * - ERROR: RTC registers are not synchronised + */ +ErrorStatus LL_RTC_WaitForSynchro(RTC_TypeDef *RTCx) +{ + __IO uint32_t timeout = RTC_SYNCHRO_TIMEOUT; + ErrorStatus status = SUCCESS; + uint32_t tmp = 0U; + + /* Check the parameter */ + assert_param(IS_RTC_ALL_INSTANCE(RTCx)); + + /* Clear RSF flag */ + LL_RTC_ClearFlag_RS(RTCx); + + /* Wait the registers to be synchronised */ + tmp = LL_RTC_IsActiveFlag_RS(RTCx); + while ((timeout != 0U) && (tmp != 1U)) + { + if (LL_SYSTICK_IsActiveCounterFlag() == 1U) + { + timeout--; + } + tmp = LL_RTC_IsActiveFlag_RS(RTCx); + if (timeout == 0U) + { + status = ERROR; + } + } + + return (status); +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined(RTC) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c new file mode 100644 index 0000000..ab48303 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c @@ -0,0 +1,1578 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_sdmmc.c + * @author MCD Application Team + * @brief SDMMC Low Layer HAL module driver. + * + * This file provides firmware functions to manage the following + * functionalities of the SDMMC peripheral: + * + Initialization/de-initialization functions + * + I/O operation functions + * + Peripheral Control functions + * + Peripheral State 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 + ============================================================================== + ##### SDMMC peripheral features ##### + ============================================================================== + [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB + peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA + devices. + + [..] The SDMMC features include the following: + (+) Full compliance with MultiMedia Card System Specification Version 4.2. Card support + for three different databus modes: 1-bit (default), 4-bit and 8-bit + (+) Full compatibility with previous versions of MultiMedia Cards (forward compatibility) + (+) Full compliance with SD Memory Card Specifications Version 2.0 + (+) Full compliance with SD I/O Card Specification Version 2.0: card support for two + different data bus modes: 1-bit (default) and 4-bit + (+) Full support of the CE-ATA features (full compliance with CE-ATA digital protocol + Rev1.1) + (+) Data transfer up to 48 MHz for the 8 bit mode + (+) Data and command output enable signals to control external bidirectional drivers + + ##### How to use this driver ##### + ============================================================================== + [..] + This driver is a considered as a driver of service for external devices drivers + that interfaces with the SDMMC peripheral. + According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs + is used in the device's driver to perform SDMMC operations and functionalities. + + This driver is almost transparent for the final user, it is only used to implement other + functionalities of the external device. + + [..] + (+) The SDMMC clock (SDMMCCLK = 48 MHz) is coming from a specific output (MSI, PLLUSB1CLK, + PLLUSB2CLK). Before start working with SDMMC peripheral make sure that the + PLL is well configured. + The SDMMC peripheral uses two clock signals: + (++) SDMMC adapter clock (SDMMCCLK = 48 MHz) + (++) APB2 bus clock (PCLK2) + + -@@- PCLK2 and SDMMC_CK clock frequencies must respect the following condition: + Frequency(PCLK2) >= (3 / 8 x Frequency(SDMMC_CK)) + + (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC + peripheral. + + (+) Enable the Power ON State using the SDIO_PowerState_ON() + function and disable it using the function SDIO_PowerState_OFF(). + + (+) Enable/Disable the clock using the __SDIO_ENABLE()/__SDIO_DISABLE() macros. + + (+) Enable/Disable the peripheral interrupts using the macros __SDIO_ENABLE_IT() + and __SDIO_DISABLE_IT() if you need to use interrupt mode. + + (+) When using the DMA mode + (++) Configure the DMA in the MSP layer of the external device + (++) Active the needed channel Request + (++) Enable the DMA using __SDIO_DMA_ENABLE() macro or Disable it using the macro + __SDIO_DMA_DISABLE(). + + (+) To control the CPSM (Command Path State Machine) and send + commands to the card use the SDIO_SendCommand(), + SDIO_GetCommandResponse() and SDIO_GetResponse() functions. First, user has + to fill the command structure (pointer to SDIO_CmdInitTypeDef) according + to the selected command to be sent. + The parameters that should be filled are: + (++) Command Argument + (++) Command Index + (++) Command Response type + (++) Command Wait + (++) CPSM Status (Enable or Disable). + + -@@- To check if the command is well received, read the SDIO_CMDRESP + register using the SDIO_GetCommandResponse(). + The SDMMC responses registers (SDIO_RESP1 to SDIO_RESP2), use the + SDIO_GetResponse() function. + + (+) To control the DPSM (Data Path State Machine) and send/receive + data to/from the card use the SDIO_DataConfig(), SDIO_GetDataCounter(), + SDIO_ReadFIFO(), SDIO_WriteFIFO() and SDIO_GetFIFOCount() functions. + + *** Read Operations *** + ======================= + [..] + (#) First, user has to fill the data structure (pointer to + SDIO_DataInitTypeDef) according to the selected data type to be received. + The parameters that should be filled are: + (++) Data TimeOut + (++) Data Length + (++) Data Block size + (++) Data Transfer direction: should be from card (To SDMMC) + (++) Data Transfer mode + (++) DPSM Status (Enable or Disable) + + (#) Configure the SDMMC resources to receive the data from the card + according to selected transfer mode (Refer to Step 8, 9 and 10). + + (#) Send the selected Read command (refer to step 11). + + (#) Use the SDIO flags/interrupts to check the transfer status. + + *** Write Operations *** + ======================== + [..] + (#) First, user has to fill the data structure (pointer to + SDIO_DataInitTypeDef) according to the selected data type to be received. + The parameters that should be filled are: + (++) Data TimeOut + (++) Data Length + (++) Data Block size + (++) Data Transfer direction: should be to card (To CARD) + (++) Data Transfer mode + (++) DPSM Status (Enable or Disable) + + (#) Configure the SDMMC resources to send the data to the card according to + selected transfer mode. + + (#) Send the selected Write command. + + (#) Use the SDIO flags/interrupts to check the transfer status. + + *** Command management operations *** + ===================================== + [..] + (#) The commands used for Read/Write/Erase operations are managed in + separate functions. + Each function allows to send the needed command with the related argument, + then check the response. + By the same approach, you could implement a command and check the response. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +#if defined(SDIO) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @defgroup SDMMC_LL SDMMC Low Layer + * @brief Low layer module for SD + * @{ + */ + +#if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_MMC_MODULE_ENABLED) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx); + +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions + * @{ + */ + +/** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions + * @brief Initialization and Configuration functions + * +@verbatim + =============================================================================== + ##### Initialization/de-initialization functions ##### + =============================================================================== + [..] This section provides functions allowing to: + +@endverbatim + * @{ + */ + +/** + * @brief Initializes the SDMMC according to the specified + * parameters in the SDMMC_InitTypeDef and create the associated handle. + * @param SDIOx: Pointer to SDMMC register base + * @param Init: SDMMC initialization structure + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_ALL_INSTANCE(SDIOx)); + assert_param(IS_SDIO_CLOCK_EDGE(Init.ClockEdge)); + assert_param(IS_SDIO_CLOCK_BYPASS(Init.ClockBypass)); + assert_param(IS_SDIO_CLOCK_POWER_SAVE(Init.ClockPowerSave)); + assert_param(IS_SDIO_BUS_WIDE(Init.BusWide)); + assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl)); + assert_param(IS_SDIO_CLKDIV(Init.ClockDiv)); + + /* Set SDMMC configuration parameters */ + tmpreg |= (Init.ClockEdge |\ + Init.ClockBypass |\ + Init.ClockPowerSave |\ + Init.BusWide |\ + Init.HardwareFlowControl |\ + Init.ClockDiv + ); + + /* Write to SDMMC CLKCR */ + MODIFY_REG(SDIOx->CLKCR, CLKCR_CLEAR_MASK, tmpreg); + + return HAL_OK; +} + + +/** + * @} + */ + +/** @defgroup HAL_SDMMC_LL_Group2 IO operation functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### I/O operation functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the SDMMC data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Read data (word) from Rx FIFO in blocking mode (polling) + * @param SDIOx: Pointer to SDMMC register base + * @retval HAL status + */ +uint32_t SDIO_ReadFIFO(SDIO_TypeDef *SDIOx) +{ + /* Read data from Rx FIFO */ + return (SDIOx->FIFO); +} + +/** + * @brief Write data (word) to Tx FIFO in blocking mode (polling) + * @param SDIOx: Pointer to SDMMC register base + * @param pWriteData: pointer to data to write + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_WriteFIFO(SDIO_TypeDef *SDIOx, uint32_t *pWriteData) +{ + /* Write data to FIFO */ + SDIOx->FIFO = *pWriteData; + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions + * @brief management functions + * +@verbatim + =============================================================================== + ##### Peripheral Control functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to control the SDMMC data + transfers. + +@endverbatim + * @{ + */ + +/** + * @brief Set SDMMC Power state to ON. + * @param SDIOx: Pointer to SDMMC register base + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_PowerState_ON(SDIO_TypeDef *SDIOx) +{ + /* Set power state to ON */ + SDIOx->POWER = SDIO_POWER_PWRCTRL; + + return HAL_OK; +} + +/** + * @brief Set SDMMC Power state to OFF. + * @param SDIOx: Pointer to SDMMC register base + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_PowerState_OFF(SDIO_TypeDef *SDIOx) +{ + /* Set power state to OFF */ + SDIOx->POWER = (uint32_t)0x00000000; + + return HAL_OK; +} + +/** + * @brief Get SDMMC Power state. + * @param SDIOx: Pointer to SDMMC register base + * @retval Power status of the controller. The returned value can be one of the + * following values: + * - 0x00: Power OFF + * - 0x02: Power UP + * - 0x03: Power ON + */ +uint32_t SDIO_GetPowerState(SDIO_TypeDef *SDIOx) +{ + return (SDIOx->POWER & SDIO_POWER_PWRCTRL); +} + +/** + * @brief Configure the SDMMC command path according to the specified parameters in + * SDIO_CmdInitTypeDef structure and send the command + * @param SDIOx: Pointer to SDMMC register base + * @param Command: pointer to a SDIO_CmdInitTypeDef structure that contains + * the configuration information for the SDMMC command + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_SendCommand(SDIO_TypeDef *SDIOx, SDIO_CmdInitTypeDef *Command) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_CMD_INDEX(Command->CmdIndex)); + assert_param(IS_SDIO_RESPONSE(Command->Response)); + assert_param(IS_SDIO_WAIT(Command->WaitForInterrupt)); + assert_param(IS_SDIO_CPSM(Command->CPSM)); + + /* Set the SDMMC Argument value */ + SDIOx->ARG = Command->Argument; + + /* Set SDMMC command parameters */ + tmpreg |= (uint32_t)(Command->CmdIndex |\ + Command->Response |\ + Command->WaitForInterrupt |\ + Command->CPSM); + + /* Write to SDMMC CMD register */ + MODIFY_REG(SDIOx->CMD, CMD_CLEAR_MASK, tmpreg); + + return HAL_OK; +} + +/** + * @brief Return the command index of last command for which response received + * @param SDIOx: Pointer to SDMMC register base + * @retval Command index of the last command response received + */ +uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx) +{ + return (uint8_t)(SDIOx->RESPCMD); +} + + +/** + * @brief Return the response received from the card for the last command + * @param SDIOx: Pointer to SDMMC register base + * @param Response: Specifies the SDMMC response register. + * This parameter can be one of the following values: + * @arg SDIO_RESP1: Response Register 1 + * @arg SDIO_RESP2: Response Register 2 + * @arg SDIO_RESP3: Response Register 3 + * @arg SDIO_RESP4: Response Register 4 + * @retval The Corresponding response register value + */ +uint32_t SDIO_GetResponse(SDIO_TypeDef *SDIOx, uint32_t Response) +{ + uint32_t tmp; + + /* Check the parameters */ + assert_param(IS_SDIO_RESP(Response)); + + /* Get the response */ + tmp = (uint32_t)(&(SDIOx->RESP1)) + Response; + + return (*(__IO uint32_t *) tmp); +} + +/** + * @brief Configure the SDMMC data path according to the specified + * parameters in the SDIO_DataInitTypeDef. + * @param SDIOx: Pointer to SDIO register base + * @param Data : pointer to a SDIO_DataInitTypeDef structure + * that contains the configuration information for the SDMMC data. + * @retval HAL status + */ +HAL_StatusTypeDef SDIO_ConfigData(SDIO_TypeDef *SDIOx, SDIO_DataInitTypeDef* Data) +{ + uint32_t tmpreg = 0; + + /* Check the parameters */ + assert_param(IS_SDIO_DATA_LENGTH(Data->DataLength)); + assert_param(IS_SDIO_BLOCK_SIZE(Data->DataBlockSize)); + assert_param(IS_SDIO_TRANSFER_DIR(Data->TransferDir)); + assert_param(IS_SDIO_TRANSFER_MODE(Data->TransferMode)); + assert_param(IS_SDIO_DPSM(Data->DPSM)); + + /* Set the SDMMC Data TimeOut value */ + SDIOx->DTIMER = Data->DataTimeOut; + + /* Set the SDMMC DataLength value */ + SDIOx->DLEN = Data->DataLength; + + /* Set the SDMMC data configuration parameters */ + tmpreg |= (uint32_t)(Data->DataBlockSize |\ + Data->TransferDir |\ + Data->TransferMode |\ + Data->DPSM); + + /* Write to SDMMC DCTRL */ + MODIFY_REG(SDIOx->DCTRL, DCTRL_CLEAR_MASK, tmpreg); + + return HAL_OK; + +} + +/** + * @brief Returns number of remaining data bytes to be transferred. + * @param SDIOx: Pointer to SDIO register base + * @retval Number of remaining data bytes to be transferred + */ +uint32_t SDIO_GetDataCounter(SDIO_TypeDef *SDIOx) +{ + return (SDIOx->DCOUNT); +} + +/** + * @brief Get the FIFO data + * @param SDIOx: Pointer to SDIO register base + * @retval Data received + */ +uint32_t SDIO_GetFIFOCount(SDIO_TypeDef *SDIOx) +{ + return (SDIOx->FIFO); +} + +/** + * @brief Sets one of the two options of inserting read wait interval. + * @param SDIOx: Pointer to SDIO register base + * @param SDIO_ReadWaitMode: SDMMC Read Wait operation mode. + * This parameter can be: + * @arg SDIO_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK + * @arg SDIO_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2 + * @retval None + */ +HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode) +{ + /* Check the parameters */ + assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode)); + + /* Set SDMMC read wait mode */ + MODIFY_REG(SDIOx->DCTRL, SDIO_DCTRL_RWMOD, SDIO_ReadWaitMode); + + return HAL_OK; +} + +/** + * @} + */ + + +/** @defgroup HAL_SDMMC_LL_Group4 Command management functions + * @brief Data transfers functions + * +@verbatim + =============================================================================== + ##### Commands management functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the needed commands. + +@endverbatim + * @{ + */ + +/** + * @brief Send the Data Block Length command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)BlockSize; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_BLOCKLEN; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_BLOCKLEN, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Read Single Block command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)ReadAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_SINGLE_BLOCK; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_SINGLE_BLOCK, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Read Multi Block command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)ReadAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_MULT_BLOCK; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Write Single Block command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)WriteAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_SINGLE_BLOCK; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Write Multi Block command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)WriteAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_MULT_BLOCK; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_MULT_BLOCK, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Start Address Erase command for SD and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)StartAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_START; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_START, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the End Address Erase command for SD and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)EndAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_END; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_END, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Start Address Erase command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)StartAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_START; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_START, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the End Address Erase command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = (uint32_t)EndAdd; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_END; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_END, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Erase command and check the response + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdErase(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Set Block Size for Card */ + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE, SDIO_MAXERASETIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Stop Transfer command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdStopTransfer(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD12 STOP_TRANSMISSION */ + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_STOP_TRANSMISSION; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_STOP_TRANSMISSION, SDIO_STOPTRANSFERTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Select Deselect command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param addr: Address of the card to be selected + * @retval HAL status + */ +uint32_t SDMMC_CmdSelDesel(SDIO_TypeDef *SDIOx, uint64_t Addr) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD7 SDMMC_SEL_DESEL_CARD */ + sdmmc_cmdinit.Argument = (uint32_t)Addr; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEL_DESEL_CARD; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEL_DESEL_CARD, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Go Idle State command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdGoIdleState(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_GO_IDLE_STATE; + sdmmc_cmdinit.Response = SDIO_RESPONSE_NO; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdError(SDIOx); + + return errorstate; +} + +/** + * @brief Send the Operating Condition command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdOperCond(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD8 to verify SD card interface operating condition */ + /* Argument: - [31:12]: Reserved (shall be set to '0') + - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V) + - [7:0]: Check Pattern (recommended 0xAA) */ + /* CMD Response: R7 */ + sdmmc_cmdinit.Argument = SDMMC_CHECK_PATTERN; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp7(SDIOx); + + return errorstate; +} + +/** + * @brief Send the Application command to verify that that the next command + * is an application specific com-mand rather than a standard command + * and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param Argument: Command Argument + * @retval HAL status + */ +uint32_t SDMMC_CmdAppCommand(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = (uint32_t)Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_CMD; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + /* If there is a HAL_ERROR, it is a MMC card, else + it is a SD card: SD card 2.0 (voltage range mismatch) + or SD card 1.x */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_CMD, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the command asking the accessed card to send its operating + * condition register (OCR) + * @param SDIOx: Pointer to SDIO register base + * @param Argument: Command Argument + * @retval HAL status + */ +uint32_t SDMMC_CmdAppOperCommand(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = SDMMC_VOLTAGE_WINDOW_SD | Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_OP_COND; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp3(SDIOx); + + return errorstate; +} + +/** + * @brief Send the Bus Width command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param BusWidth: BusWidth + * @retval HAL status + */ +uint32_t SDMMC_CmdBusWidth(SDIO_TypeDef *SDIOx, uint32_t BusWidth) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = (uint32_t)BusWidth; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_SD_SET_BUSWIDTH; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Send SCR command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD51 SD_APP_SEND_SCR */ + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_SEND_SCR; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_SEND_SCR, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Send CID command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD2 ALL_SEND_CID */ + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ALL_SEND_CID; + sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp2(SDIOx); + + return errorstate; +} + +/** + * @brief Send the Send CSD command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param Argument: Command Argument + * @retval HAL status + */ +uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD9 SEND_CSD */ + sdmmc_cmdinit.Argument = Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_CSD; + sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp2(SDIOx); + + return errorstate; +} + +/** + * @brief Send the Send CSD command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param pRCA: Card RCA + * @retval HAL status + */ +uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD3 SD_CMD_SET_REL_ADDR */ + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp6(SDIOx, SDMMC_CMD_SET_REL_ADDR, pRCA); + + return errorstate; +} + +/** + * @brief Send the Set Relative Address command to MMC card (not SD card). + * @param SDIOx Pointer to SDIO register base + * @param RCA Card RCA + * @retval HAL status + */ +uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD3 SD_CMD_SET_REL_ADDR */ + sdmmc_cmdinit.Argument = ((uint32_t)RCA << 16U); + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_REL_ADDR, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Status command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @param Argument: Command Argument + * @retval HAL status + */ +uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_STATUS; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEND_STATUS, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Status register command and check the response. + * @param SDIOx: Pointer to SDIO register base + * @retval HAL status + */ +uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = 0U; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_STATUS; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_STATUS, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Sends host capacity support information and activates the card's + * initialization process. Send SDMMC_CMD_SEND_OP_COND command + * @param SDIOx: Pointer to SDIO register base + * @parame Argument: Argument used for the command + * @retval HAL status + */ +uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + sdmmc_cmdinit.Argument = Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_OP_COND; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp3(SDIOx); + + return errorstate; +} + +/** + * @brief Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command + * @param SDIOx: Pointer to SDIO register base + * @parame Argument: Argument used for the command + * @retval HAL status + */ +uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */ + /* CMD Response: R1 */ + sdmmc_cmdinit.Argument = Argument; /* SDMMC_SDR25_SWITCH_PATTERN */ + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SWITCH; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SWITCH, SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @brief Send the Send EXT_CSD command and check the response. + * @param SDIOx Pointer to SDMMC register base + * @param Argument Command Argument + * @retval HAL status + */ +uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument) +{ + SDIO_CmdInitTypeDef sdmmc_cmdinit; + uint32_t errorstate; + + /* Send CMD9 SEND_CSD */ + sdmmc_cmdinit.Argument = Argument; + sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD; + sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT; + sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO; + sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE; + (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit); + + /* Check for error conditions */ + errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT); + + return errorstate; +} + +/** + * @} + */ + +/** @defgroup HAL_SDMMC_LL_Group5 Responses management functions + * @brief Responses functions + * +@verbatim + =============================================================================== + ##### Responses management functions ##### + =============================================================================== + [..] + This subsection provides a set of functions allowing to manage the needed responses. + +@endverbatim + * @{ + */ +/** + * @brief Checks for error conditions for R1 response. + * @param SDIOx Pointer to SDMMC register base + * @param SD_CMD: The sent command index + * @retval SD Card error state + */ +uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout) +{ + uint32_t response_r1; + uint32_t sta_reg; + + /* 8 is the number of required instructions cycles for the below loop statement. + The Timeout is expressed in ms */ + uint32_t count = Timeout * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + sta_reg = SDIOx->STA; + }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) || + ((sta_reg & SDIO_FLAG_CMDACT) != 0U )); + + if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); + + return SDMMC_ERROR_CMD_RSP_TIMEOUT; + } + else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL); + + return SDMMC_ERROR_CMD_CRC_FAIL; + } + else + { + /* Nothing to do */ + } + + /* Clear all the static flags */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS); + + /* Check response received is of desired command */ + if(SDIO_GetCommandResponse(SDIOx) != SD_CMD) + { + return SDMMC_ERROR_CMD_CRC_FAIL; + } + + /* We have received response, retrieve it for analysis */ + response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1); + + if((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO) + { + return SDMMC_ERROR_NONE; + } + else if((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE) + { + return SDMMC_ERROR_ADDR_OUT_OF_RANGE; + } + else if((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED) + { + return SDMMC_ERROR_ADDR_MISALIGNED; + } + else if((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR) + { + return SDMMC_ERROR_BLOCK_LEN_ERR; + } + else if((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR) + { + return SDMMC_ERROR_ERASE_SEQ_ERR; + } + else if((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM) + { + return SDMMC_ERROR_BAD_ERASE_PARAM; + } + else if((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION) + { + return SDMMC_ERROR_WRITE_PROT_VIOLATION; + } + else if((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED) + { + return SDMMC_ERROR_LOCK_UNLOCK_FAILED; + } + else if((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED) + { + return SDMMC_ERROR_COM_CRC_FAILED; + } + else if((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD) + { + return SDMMC_ERROR_ILLEGAL_CMD; + } + else if((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED) + { + return SDMMC_ERROR_CARD_ECC_FAILED; + } + else if((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR) + { + return SDMMC_ERROR_CC_ERR; + } + else if((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN) + { + return SDMMC_ERROR_STREAM_READ_UNDERRUN; + } + else if((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN) + { + return SDMMC_ERROR_STREAM_WRITE_OVERRUN; + } + else if((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE) + { + return SDMMC_ERROR_CID_CSD_OVERWRITE; + } + else if((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP) + { + return SDMMC_ERROR_WP_ERASE_SKIP; + } + else if((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED) + { + return SDMMC_ERROR_CARD_ECC_DISABLED; + } + else if((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET) + { + return SDMMC_ERROR_ERASE_RESET; + } + else if((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR) + { + return SDMMC_ERROR_AKE_SEQ_ERR; + } + else + { + return SDMMC_ERROR_GENERAL_UNKNOWN_ERR; + } +} + +/** + * @brief Checks for error conditions for R2 (CID or CSD) response. + * @param SDIOx Pointer to SDMMC register base + * @retval SD Card error state + */ +uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx) +{ + uint32_t sta_reg; + /* 8 is the number of required instructions cycles for the below loop statement. + The SDIO_CMDTIMEOUT is expressed in ms */ + uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + sta_reg = SDIOx->STA; + }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) || + ((sta_reg & SDIO_FLAG_CMDACT) != 0U )); + + if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); + + return SDMMC_ERROR_CMD_RSP_TIMEOUT; + } + else if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL); + + return SDMMC_ERROR_CMD_CRC_FAIL; + } + else + { + /* No error flag set */ + /* Clear all the static flags */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS); + } + + return SDMMC_ERROR_NONE; +} + +/** + * @brief Checks for error conditions for R3 (OCR) response. + * @param SDIOx Pointer to SDMMC register base + * @retval SD Card error state + */ +uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx) +{ + uint32_t sta_reg; + /* 8 is the number of required instructions cycles for the below loop statement. + The SDIO_CMDTIMEOUT is expressed in ms */ + uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + sta_reg = SDIOx->STA; + }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) || + ((sta_reg & SDIO_FLAG_CMDACT) != 0U )); + + if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); + + return SDMMC_ERROR_CMD_RSP_TIMEOUT; + } + else + { + /* Clear all the static flags */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS); + } + + return SDMMC_ERROR_NONE; +} + +/** + * @brief Checks for error conditions for R6 (RCA) response. + * @param SDIOx Pointer to SDMMC register base + * @param SD_CMD: The sent command index + * @param pRCA: Pointer to the variable that will contain the SD card relative + * address RCA + * @retval SD Card error state + */ +uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA) +{ + uint32_t response_r1; + uint32_t sta_reg; + + /* 8 is the number of required instructions cycles for the below loop statement. + The SDIO_CMDTIMEOUT is expressed in ms */ + uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + sta_reg = SDIOx->STA; + }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) || + ((sta_reg & SDIO_FLAG_CMDACT) != 0U )); + + if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); + + return SDMMC_ERROR_CMD_RSP_TIMEOUT; + } + else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL)) + { + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL); + + return SDMMC_ERROR_CMD_CRC_FAIL; + } + else + { + /* Nothing to do */ + } + + /* Check response received is of desired command */ + if(SDIO_GetCommandResponse(SDIOx) != SD_CMD) + { + return SDMMC_ERROR_CMD_CRC_FAIL; + } + + /* Clear all the static flags */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS); + + /* We have received response, retrieve it. */ + response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1); + + if((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD | SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO) + { + *pRCA = (uint16_t) (response_r1 >> 16); + + return SDMMC_ERROR_NONE; + } + else if((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD) + { + return SDMMC_ERROR_ILLEGAL_CMD; + } + else if((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED) + { + return SDMMC_ERROR_COM_CRC_FAILED; + } + else + { + return SDMMC_ERROR_GENERAL_UNKNOWN_ERR; + } +} + +/** + * @brief Checks for error conditions for R7 response. + * @param SDIOx Pointer to SDMMC register base + * @retval SD Card error state + */ +uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx) +{ + uint32_t sta_reg; + /* 8 is the number of required instructions cycles for the below loop statement. + The SDIO_CMDTIMEOUT is expressed in ms */ + uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + sta_reg = SDIOx->STA; + }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) || + ((sta_reg & SDIO_FLAG_CMDACT) != 0U )); + + if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT)) + { + /* Card is SD V2.0 compliant */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT); + + return SDMMC_ERROR_CMD_RSP_TIMEOUT; + } + else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL)) + { + /* Card is SD V2.0 compliant */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL); + + return SDMMC_ERROR_CMD_CRC_FAIL; + } + else + { + /* Nothing to do */ + } + + if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDREND)) + { + /* Card is SD V2.0 compliant */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CMDREND); + } + + return SDMMC_ERROR_NONE; + +} + +/** + * @} + */ + +/* Private function ----------------------------------------------------------*/ +/** @addtogroup SD_Private_Functions + * @{ + */ + +/** + * @brief Checks for error conditions for CMD0. + * @param SDIOx Pointer to SDMMC register base + * @retval SD Card error state + */ +static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx) +{ + /* 8 is the number of required instructions cycles for the below loop statement. + The SDIO_CMDTIMEOUT is expressed in ms */ + uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U); + + do + { + if (count-- == 0U) + { + return SDMMC_ERROR_TIMEOUT; + } + + }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT)); + + /* Clear all the static flags */ + __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS); + + return SDMMC_ERROR_NONE; +} + + +/** + * @} + */ + +#endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */ +/** + * @} + */ + +/** + * @} + */ + +#endif /* SDIO */ diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c new file mode 100644 index 0000000..02a0740 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_spi.c @@ -0,0 +1,624 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_spi.c + * @author MCD Application Team + * @brief SPI LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_spi.h" +#include "stm32f4xx_ll_bus.h" +#include "stm32f4xx_ll_rcc.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4) || defined (SPI5) || defined(SPI6) + +/** @addtogroup SPI_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Private constants ---------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Constants SPI Private Constants + * @{ + */ +/* SPI registers Masks */ +#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \ + SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \ + SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_DFF | \ + SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \ + SPI_CR1_BIDIMODE) +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup SPI_LL_Private_Macros SPI Private Macros + * @{ + */ +#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \ + || ((__VALUE__) == LL_SPI_SIMPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \ + || ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX)) + +#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \ + || ((__VALUE__) == LL_SPI_MODE_SLAVE)) + +#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \ + || ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT)) + +#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \ + || ((__VALUE__) == LL_SPI_POLARITY_HIGH)) + +#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \ + || ((__VALUE__) == LL_SPI_PHASE_2EDGE)) + +#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \ + || ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT)) + +#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \ + || ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256)) + +#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \ + || ((__VALUE__) == LL_SPI_MSB_FIRST)) + +#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \ + || ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE)) + +#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup SPI_LL_Exported_Functions + * @{ + */ + +/** @addtogroup SPI_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the SPI registers to their default reset values. + * @param SPIx SPI Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: SPI registers are de-initialized + * - ERROR: SPI registers are not de-initialized + */ +ErrorStatus LL_SPI_DeInit(SPI_TypeDef *SPIx) +{ + ErrorStatus status = ERROR; + + /* Check the parameters */ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + +#if defined(SPI1) + if (SPIx == SPI1) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1); + + status = SUCCESS; + } +#endif /* SPI1 */ +#if defined(SPI2) + if (SPIx == SPI2) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2); + + status = SUCCESS; + } +#endif /* SPI2 */ +#if defined(SPI3) + if (SPIx == SPI3) + { + /* Force reset of SPI clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3); + + /* Release reset of SPI clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3); + + status = SUCCESS; + } +#endif /* SPI3 */ +#if defined(SPI4) + if (SPIx == SPI4) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI4); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI4); + + status = SUCCESS; + } +#endif /* SPI4 */ +#if defined(SPI5) + if (SPIx == SPI5) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI5); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI5); + + status = SUCCESS; + } +#endif /* SPI5 */ +#if defined(SPI6) + if (SPIx == SPI6) + { + /* Force reset of SPI clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI6); + + /* Release reset of SPI clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI6); + + status = SUCCESS; + } +#endif /* SPI6 */ + + return status; +} + +/** + * @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct. + * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0), + * SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @param SPIx SPI Instance + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * @retval An ErrorStatus enumeration value. (Return always SUCCESS) + */ +ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct) +{ + ErrorStatus status = ERROR; + + /* Check the SPI Instance SPIx*/ + assert_param(IS_SPI_ALL_INSTANCE(SPIx)); + + /* Check the SPI parameters from SPI_InitStruct*/ + assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection)); + assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode)); + assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth)); + assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity)); + assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase)); + assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS)); + assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate)); + assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder)); + assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation)); + + if (LL_SPI_IsEnabled(SPIx) == 0x00000000U) + { + /*---------------------------- SPIx CR1 Configuration ------------------------ + * Configure SPIx CR1 with parameters: + * - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits + * - Master/Slave Mode: SPI_CR1_MSTR bit + * - DataWidth: SPI_CR1_DFF bit + * - ClockPolarity: SPI_CR1_CPOL bit + * - ClockPhase: SPI_CR1_CPHA bit + * - NSS management: SPI_CR1_SSM bit + * - BaudRate prescaler: SPI_CR1_BR[2:0] bits + * - BitOrder: SPI_CR1_LSBFIRST bit + * - CRCCalculation: SPI_CR1_CRCEN bit + */ + MODIFY_REG(SPIx->CR1, + SPI_CR1_CLEAR_MASK, + SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode | SPI_InitStruct->DataWidth | + SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase | + SPI_InitStruct->NSS | SPI_InitStruct->BaudRate | + SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation); + + /*---------------------------- SPIx CR2 Configuration ------------------------ + * Configure SPIx CR2 with parameters: + * - NSS management: SSOE bit + */ + MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, (SPI_InitStruct->NSS >> 16U)); + + /*---------------------------- SPIx CRCPR Configuration ---------------------- + * Configure SPIx CRCPR with parameters: + * - CRCPoly: CRCPOLY[15:0] bits + */ + if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE) + { + assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly)); + LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly); + } + status = SUCCESS; + } + + /* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */ + CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD); + return status; +} + +/** + * @brief Set each @ref LL_SPI_InitTypeDef field to default value. + * @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct) +{ + /* Set SPI_InitStruct fields to default values */ + SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX; + SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE; + SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT; + SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW; + SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE; + SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT; + SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2; + SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST; + SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE; + SPI_InitStruct->CRCPoly = 7U; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup I2S_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @defgroup I2S_LL_Private_Constants I2S Private Constants + * @{ + */ +/* I2S registers Masks */ +#define I2S_I2SCFGR_CLEAR_MASK (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \ + SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \ + SPI_I2SCFGR_I2SCFG | SPI_I2SCFGR_I2SMOD ) + +#define I2S_I2SPR_CLEAR_MASK 0x0002U +/** + * @} + */ +/* Private macros ------------------------------------------------------------*/ +/** @defgroup I2S_LL_Private_Macros I2S Private Macros + * @{ + */ + +#define IS_LL_I2S_DATAFORMAT(__VALUE__) (((__VALUE__) == LL_I2S_DATAFORMAT_16B) \ + || ((__VALUE__) == LL_I2S_DATAFORMAT_16B_EXTENDED) \ + || ((__VALUE__) == LL_I2S_DATAFORMAT_24B) \ + || ((__VALUE__) == LL_I2S_DATAFORMAT_32B)) + +#define IS_LL_I2S_CPOL(__VALUE__) (((__VALUE__) == LL_I2S_POLARITY_LOW) \ + || ((__VALUE__) == LL_I2S_POLARITY_HIGH)) + +#define IS_LL_I2S_STANDARD(__VALUE__) (((__VALUE__) == LL_I2S_STANDARD_PHILIPS) \ + || ((__VALUE__) == LL_I2S_STANDARD_MSB) \ + || ((__VALUE__) == LL_I2S_STANDARD_LSB) \ + || ((__VALUE__) == LL_I2S_STANDARD_PCM_SHORT) \ + || ((__VALUE__) == LL_I2S_STANDARD_PCM_LONG)) + +#define IS_LL_I2S_MODE(__VALUE__) (((__VALUE__) == LL_I2S_MODE_SLAVE_TX) \ + || ((__VALUE__) == LL_I2S_MODE_SLAVE_RX) \ + || ((__VALUE__) == LL_I2S_MODE_MASTER_TX) \ + || ((__VALUE__) == LL_I2S_MODE_MASTER_RX)) + +#define IS_LL_I2S_MCLK_OUTPUT(__VALUE__) (((__VALUE__) == LL_I2S_MCLK_OUTPUT_ENABLE) \ + || ((__VALUE__) == LL_I2S_MCLK_OUTPUT_DISABLE)) + +#define IS_LL_I2S_AUDIO_FREQ(__VALUE__) ((((__VALUE__) >= LL_I2S_AUDIOFREQ_8K) \ + && ((__VALUE__) <= LL_I2S_AUDIOFREQ_192K)) \ + || ((__VALUE__) == LL_I2S_AUDIOFREQ_DEFAULT)) + +#define IS_LL_I2S_PRESCALER_LINEAR(__VALUE__) ((__VALUE__) >= 0x2U) + +#define IS_LL_I2S_PRESCALER_PARITY(__VALUE__) (((__VALUE__) == LL_I2S_PRESCALER_PARITY_EVEN) \ + || ((__VALUE__) == LL_I2S_PRESCALER_PARITY_ODD)) +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup I2S_LL_Exported_Functions + * @{ + */ + +/** @addtogroup I2S_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize the SPI/I2S registers to their default reset values. + * @param SPIx SPI Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: SPI registers are de-initialized + * - ERROR: SPI registers are not de-initialized + */ +ErrorStatus LL_I2S_DeInit(SPI_TypeDef *SPIx) +{ + return LL_SPI_DeInit(SPIx); +} + +/** + * @brief Initializes the SPI/I2S registers according to the specified parameters in I2S_InitStruct. + * @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0), + * SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @param SPIx SPI Instance + * @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: SPI registers are Initialized + * - ERROR: SPI registers are not Initialized + */ +ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct) +{ + uint32_t i2sdiv = 2U; + uint32_t i2sodd = 0U; + uint32_t packetlength = 1U; + uint32_t tmp; + uint32_t sourceclock; + ErrorStatus status = ERROR; + + /* Check the I2S parameters */ + assert_param(IS_I2S_ALL_INSTANCE(SPIx)); + assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode)); + assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard)); + assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat)); + assert_param(IS_LL_I2S_MCLK_OUTPUT(I2S_InitStruct->MCLKOutput)); + assert_param(IS_LL_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFreq)); + assert_param(IS_LL_I2S_CPOL(I2S_InitStruct->ClockPolarity)); + + if (LL_I2S_IsEnabled(SPIx) == 0x00000000U) + { + /*---------------------------- SPIx I2SCFGR Configuration -------------------- + * Configure SPIx I2SCFGR with parameters: + * - Mode: SPI_I2SCFGR_I2SCFG[1:0] bit + * - Standard: SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits + * - DataFormat: SPI_I2SCFGR_CHLEN and SPI_I2SCFGR_DATLEN bits + * - ClockPolarity: SPI_I2SCFGR_CKPOL bit + */ + + /* Write to SPIx I2SCFGR */ + MODIFY_REG(SPIx->I2SCFGR, + I2S_I2SCFGR_CLEAR_MASK, + I2S_InitStruct->Mode | I2S_InitStruct->Standard | + I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity | + SPI_I2SCFGR_I2SMOD); + + /*---------------------------- SPIx I2SPR Configuration ---------------------- + * Configure SPIx I2SPR with parameters: + * - MCLKOutput: SPI_I2SPR_MCKOE bit + * - AudioFreq: SPI_I2SPR_I2SDIV[7:0] and SPI_I2SPR_ODD bits + */ + + /* If the requested audio frequency is not the default, compute the prescaler (i2sodd, i2sdiv) + * else, default values are used: i2sodd = 0U, i2sdiv = 2U. + */ + if (I2S_InitStruct->AudioFreq != LL_I2S_AUDIOFREQ_DEFAULT) + { + /* Check the frame length (For the Prescaler computing) + * Default value: LL_I2S_DATAFORMAT_16B (packetlength = 1U). + */ + if (I2S_InitStruct->DataFormat != LL_I2S_DATAFORMAT_16B) + { + /* Packet length is 32 bits */ + packetlength = 2U; + } + + /* If an external I2S clock has to be used, the specific define should be set + in the project configuration or in the stm32f4xx_ll_rcc.h file */ + /* Get the I2S source clock value */ + sourceclock = LL_RCC_GetI2SClockFreq(LL_RCC_I2S1_CLKSOURCE); + + /* Compute the Real divider depending on the MCLK output state with a floating point */ + if (I2S_InitStruct->MCLKOutput == LL_I2S_MCLK_OUTPUT_ENABLE) + { + /* MCLK output is enabled */ + tmp = (((((sourceclock / 256U) * 10U) / I2S_InitStruct->AudioFreq)) + 5U); + } + else + { + /* MCLK output is disabled */ + tmp = (((((sourceclock / (32U * packetlength)) * 10U) / I2S_InitStruct->AudioFreq)) + 5U); + } + + /* Remove the floating point */ + tmp = tmp / 10U; + + /* Check the parity of the divider */ + i2sodd = (tmp & (uint16_t)0x0001U); + + /* Compute the i2sdiv prescaler */ + i2sdiv = ((tmp - i2sodd) / 2U); + + /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */ + i2sodd = (i2sodd << 8U); + } + + /* Test if the divider is 1 or 0 or greater than 0xFF */ + if ((i2sdiv < 2U) || (i2sdiv > 0xFFU)) + { + /* Set the default values */ + i2sdiv = 2U; + i2sodd = 0U; + } + + /* Write to SPIx I2SPR register the computed value */ + WRITE_REG(SPIx->I2SPR, i2sdiv | i2sodd | I2S_InitStruct->MCLKOutput); + + status = SUCCESS; + } + return status; +} + +/** + * @brief Set each @ref LL_I2S_InitTypeDef field to default value. + * @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct) +{ + /*--------------- Reset I2S init structure parameters values -----------------*/ + I2S_InitStruct->Mode = LL_I2S_MODE_SLAVE_TX; + I2S_InitStruct->Standard = LL_I2S_STANDARD_PHILIPS; + I2S_InitStruct->DataFormat = LL_I2S_DATAFORMAT_16B; + I2S_InitStruct->MCLKOutput = LL_I2S_MCLK_OUTPUT_DISABLE; + I2S_InitStruct->AudioFreq = LL_I2S_AUDIOFREQ_DEFAULT; + I2S_InitStruct->ClockPolarity = LL_I2S_POLARITY_LOW; +} + +/** + * @brief Set linear and parity prescaler. + * @note To calculate value of PrescalerLinear(I2SDIV[7:0] bits) and PrescalerParity(ODD bit)\n + * Check Audio frequency table and formulas inside Reference Manual (SPI/I2S). + * @param SPIx SPI Instance + * @param PrescalerLinear value Min_Data=0x02 and Max_Data=0xFF. + * @param PrescalerParity This parameter can be one of the following values: + * @arg @ref LL_I2S_PRESCALER_PARITY_EVEN + * @arg @ref LL_I2S_PRESCALER_PARITY_ODD + * @retval None + */ +void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity) +{ + /* Check the I2S parameters */ + assert_param(IS_I2S_ALL_INSTANCE(SPIx)); + assert_param(IS_LL_I2S_PRESCALER_LINEAR(PrescalerLinear)); + assert_param(IS_LL_I2S_PRESCALER_PARITY(PrescalerParity)); + + /* Write to SPIx I2SPR */ + MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_I2SDIV | SPI_I2SPR_ODD, PrescalerLinear | (PrescalerParity << 8U)); +} + +#if defined (SPI_I2S_FULLDUPLEX_SUPPORT) +/** + * @brief Configures the full duplex mode for the I2Sx peripheral using its extension + * I2Sxext according to the specified parameters in the I2S_InitStruct. + * @note The structure pointed by I2S_InitStruct parameter should be the same + * used for the master I2S peripheral. In this case, if the master is + * configured as transmitter, the slave will be receiver and vice versa. + * Or you can force a different mode by modifying the field I2S_Mode to the + * value I2S_SlaveRx or I2S_SlaveTx independently of the master configuration. + * @param I2Sxext SPI Instance + * @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: I2Sxext registers are Initialized + * - ERROR: I2Sxext registers are not Initialized + */ +ErrorStatus LL_I2S_InitFullDuplex(SPI_TypeDef *I2Sxext, LL_I2S_InitTypeDef *I2S_InitStruct) +{ + uint32_t mode = 0U; + ErrorStatus status = ERROR; + + /* Check the I2S parameters */ + assert_param(IS_I2S_EXT_ALL_INSTANCE(I2Sxext)); + assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode)); + assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard)); + assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat)); + assert_param(IS_LL_I2S_CPOL(I2S_InitStruct->ClockPolarity)); + + if (LL_I2S_IsEnabled(I2Sxext) == 0x00000000U) + { + /*---------------------------- SPIx I2SCFGR Configuration -------------------- + * Configure SPIx I2SCFGR with parameters: + * - Mode: SPI_I2SCFGR_I2SCFG[1:0] bit + * - Standard: SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits + * - DataFormat: SPI_I2SCFGR_CHLEN and SPI_I2SCFGR_DATLEN bits + * - ClockPolarity: SPI_I2SCFGR_CKPOL bit + */ + + /* Reset I2SPR registers */ + WRITE_REG(I2Sxext->I2SPR, I2S_I2SPR_CLEAR_MASK); + + /* Get the mode to be configured for the extended I2S */ + if ((I2S_InitStruct->Mode == LL_I2S_MODE_MASTER_TX) || (I2S_InitStruct->Mode == LL_I2S_MODE_SLAVE_TX)) + { + mode = LL_I2S_MODE_SLAVE_RX; + } + else + { + if ((I2S_InitStruct->Mode == LL_I2S_MODE_MASTER_RX) || (I2S_InitStruct->Mode == LL_I2S_MODE_SLAVE_RX)) + { + mode = LL_I2S_MODE_SLAVE_TX; + } + } + + /* Write to SPIx I2SCFGR */ + MODIFY_REG(I2Sxext->I2SCFGR, + I2S_I2SCFGR_CLEAR_MASK, + I2S_InitStruct->Standard | + I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity | + SPI_I2SCFGR_I2SMOD | mode); + + status = SUCCESS; + } + return status; +} +#endif /* SPI_I2S_FULLDUPLEX_SUPPORT */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) || defined (SPI4) || defined (SPI5) || defined(SPI6) */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c new file mode 100644 index 0000000..a0890c3 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_tim.c @@ -0,0 +1,1189 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_tim.c + * @author MCD Application Team + * @brief TIM LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_tim.h" +#include "stm32f4xx_ll_bus.h" + +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (TIM1) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM6) || defined (TIM7) || defined (TIM8) || defined (TIM9) || defined (TIM10) || defined (TIM11) || defined (TIM12) || defined (TIM13) || defined (TIM14) + +/** @addtogroup TIM_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup TIM_LL_Private_Macros + * @{ + */ +#define IS_LL_TIM_COUNTERMODE(__VALUE__) (((__VALUE__) == LL_TIM_COUNTERMODE_UP) \ + || ((__VALUE__) == LL_TIM_COUNTERMODE_DOWN) \ + || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP) \ + || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_DOWN) \ + || ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP_DOWN)) + +#define IS_LL_TIM_CLOCKDIVISION(__VALUE__) (((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV1) \ + || ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV2) \ + || ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV4)) + +#define IS_LL_TIM_OCMODE(__VALUE__) (((__VALUE__) == LL_TIM_OCMODE_FROZEN) \ + || ((__VALUE__) == LL_TIM_OCMODE_ACTIVE) \ + || ((__VALUE__) == LL_TIM_OCMODE_INACTIVE) \ + || ((__VALUE__) == LL_TIM_OCMODE_TOGGLE) \ + || ((__VALUE__) == LL_TIM_OCMODE_FORCED_INACTIVE) \ + || ((__VALUE__) == LL_TIM_OCMODE_FORCED_ACTIVE) \ + || ((__VALUE__) == LL_TIM_OCMODE_PWM1) \ + || ((__VALUE__) == LL_TIM_OCMODE_PWM2)) + +#define IS_LL_TIM_OCSTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCSTATE_DISABLE) \ + || ((__VALUE__) == LL_TIM_OCSTATE_ENABLE)) + +#define IS_LL_TIM_OCPOLARITY(__VALUE__) (((__VALUE__) == LL_TIM_OCPOLARITY_HIGH) \ + || ((__VALUE__) == LL_TIM_OCPOLARITY_LOW)) + +#define IS_LL_TIM_OCIDLESTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCIDLESTATE_LOW) \ + || ((__VALUE__) == LL_TIM_OCIDLESTATE_HIGH)) + +#define IS_LL_TIM_ACTIVEINPUT(__VALUE__) (((__VALUE__) == LL_TIM_ACTIVEINPUT_DIRECTTI) \ + || ((__VALUE__) == LL_TIM_ACTIVEINPUT_INDIRECTTI) \ + || ((__VALUE__) == LL_TIM_ACTIVEINPUT_TRC)) + +#define IS_LL_TIM_ICPSC(__VALUE__) (((__VALUE__) == LL_TIM_ICPSC_DIV1) \ + || ((__VALUE__) == LL_TIM_ICPSC_DIV2) \ + || ((__VALUE__) == LL_TIM_ICPSC_DIV4) \ + || ((__VALUE__) == LL_TIM_ICPSC_DIV8)) + +#define IS_LL_TIM_IC_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_IC_FILTER_FDIV1) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N2) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N4) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N8) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N6) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N8) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N6) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N8) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N6) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N8) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N5) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N6) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N8) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N5) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N6) \ + || ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N8)) + +#define IS_LL_TIM_IC_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \ + || ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING) \ + || ((__VALUE__) == LL_TIM_IC_POLARITY_BOTHEDGE)) + +#define IS_LL_TIM_ENCODERMODE(__VALUE__) (((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI1) \ + || ((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI2) \ + || ((__VALUE__) == LL_TIM_ENCODERMODE_X4_TI12)) + +#define IS_LL_TIM_IC_POLARITY_ENCODER(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \ + || ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING)) + +#define IS_LL_TIM_OSSR_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSR_DISABLE) \ + || ((__VALUE__) == LL_TIM_OSSR_ENABLE)) + +#define IS_LL_TIM_OSSI_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSI_DISABLE) \ + || ((__VALUE__) == LL_TIM_OSSI_ENABLE)) + +#define IS_LL_TIM_LOCK_LEVEL(__VALUE__) (((__VALUE__) == LL_TIM_LOCKLEVEL_OFF) \ + || ((__VALUE__) == LL_TIM_LOCKLEVEL_1) \ + || ((__VALUE__) == LL_TIM_LOCKLEVEL_2) \ + || ((__VALUE__) == LL_TIM_LOCKLEVEL_3)) + +#define IS_LL_TIM_BREAK_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_DISABLE) \ + || ((__VALUE__) == LL_TIM_BREAK_ENABLE)) + +#define IS_LL_TIM_BREAK_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_POLARITY_LOW) \ + || ((__VALUE__) == LL_TIM_BREAK_POLARITY_HIGH)) + +#define IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(__VALUE__) (((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_DISABLE) \ + || ((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_ENABLE)) +/** + * @} + */ + + +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup TIM_LL_Private_Functions TIM Private Functions + * @{ + */ +static ErrorStatus OC1Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct); +static ErrorStatus OC2Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct); +static ErrorStatus OC3Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct); +static ErrorStatus OC4Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct); +static ErrorStatus IC1Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct); +static ErrorStatus IC2Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct); +static ErrorStatus IC3Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct); +static ErrorStatus IC4Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup TIM_LL_Exported_Functions + * @{ + */ + +/** @addtogroup TIM_LL_EF_Init + * @{ + */ + +/** + * @brief Set TIMx registers to their reset values. + * @param TIMx Timer instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: invalid TIMx instance + */ +ErrorStatus LL_TIM_DeInit(TIM_TypeDef *TIMx) +{ + ErrorStatus result = SUCCESS; + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(TIMx)); + + if (TIMx == TIM1) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM1); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM1); + } +#if defined(TIM2) + else if (TIMx == TIM2) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM2); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM2); + } +#endif /* TIM2 */ +#if defined(TIM3) + else if (TIMx == TIM3) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM3); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM3); + } +#endif /* TIM3 */ +#if defined(TIM4) + else if (TIMx == TIM4) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM4); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM4); + } +#endif /* TIM4 */ +#if defined(TIM5) + else if (TIMx == TIM5) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM5); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM5); + } +#endif /* TIM5 */ +#if defined(TIM6) + else if (TIMx == TIM6) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM6); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM6); + } +#endif /* TIM6 */ +#if defined (TIM7) + else if (TIMx == TIM7) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM7); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM7); + } +#endif /* TIM7 */ +#if defined(TIM8) + else if (TIMx == TIM8) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM8); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM8); + } +#endif /* TIM8 */ +#if defined(TIM9) + else if (TIMx == TIM9) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM9); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM9); + } +#endif /* TIM9 */ +#if defined(TIM10) + else if (TIMx == TIM10) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM10); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM10); + } +#endif /* TIM10 */ +#if defined(TIM11) + else if (TIMx == TIM11) + { + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM11); + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM11); + } +#endif /* TIM11 */ +#if defined(TIM12) + else if (TIMx == TIM12) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM12); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM12); + } +#endif /* TIM12 */ +#if defined(TIM13) + else if (TIMx == TIM13) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM13); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM13); + } +#endif /* TIM13 */ +#if defined(TIM14) + else if (TIMx == TIM14) + { + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM14); + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM14); + } +#endif /* TIM14 */ + else + { + result = ERROR; + } + + return result; +} + +/** + * @brief Set the fields of the time base unit configuration data structure + * to their default values. + * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (time base unit configuration data structure) + * @retval None + */ +void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct) +{ + /* Set the default configuration */ + TIM_InitStruct->Prescaler = (uint16_t)0x0000; + TIM_InitStruct->CounterMode = LL_TIM_COUNTERMODE_UP; + TIM_InitStruct->Autoreload = 0xFFFFFFFFU; + TIM_InitStruct->ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; + TIM_InitStruct->RepetitionCounter = 0x00000000U; +} + +/** + * @brief Configure the TIMx time base unit. + * @param TIMx Timer Instance + * @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure + * (TIMx time base unit configuration data structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, const LL_TIM_InitTypeDef *TIM_InitStruct) +{ + uint32_t tmpcr1; + + /* Check the parameters */ + assert_param(IS_TIM_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_COUNTERMODE(TIM_InitStruct->CounterMode)); + assert_param(IS_LL_TIM_CLOCKDIVISION(TIM_InitStruct->ClockDivision)); + + tmpcr1 = LL_TIM_ReadReg(TIMx, CR1); + + if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx)) + { + /* Select the Counter Mode */ + MODIFY_REG(tmpcr1, (TIM_CR1_DIR | TIM_CR1_CMS), TIM_InitStruct->CounterMode); + } + + if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx)) + { + /* Set the clock division */ + MODIFY_REG(tmpcr1, TIM_CR1_CKD, TIM_InitStruct->ClockDivision); + } + + /* Write to TIMx CR1 */ + LL_TIM_WriteReg(TIMx, CR1, tmpcr1); + + /* Set the Autoreload value */ + LL_TIM_SetAutoReload(TIMx, TIM_InitStruct->Autoreload); + + /* Set the Prescaler value */ + LL_TIM_SetPrescaler(TIMx, TIM_InitStruct->Prescaler); + + if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx)) + { + /* Set the Repetition Counter value */ + LL_TIM_SetRepetitionCounter(TIMx, TIM_InitStruct->RepetitionCounter); + } + + /* Generate an update event to reload the Prescaler + and the repetition counter value (if applicable) immediately */ + LL_TIM_GenerateEvent_UPDATE(TIMx); + + return SUCCESS; +} + +/** + * @brief Set the fields of the TIMx output channel configuration data + * structure to their default values. + * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure + * (the output channel configuration data structure) + * @retval None + */ +void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct) +{ + /* Set the default configuration */ + TIM_OC_InitStruct->OCMode = LL_TIM_OCMODE_FROZEN; + TIM_OC_InitStruct->OCState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct->OCNState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct->CompareValue = 0x00000000U; + TIM_OC_InitStruct->OCPolarity = LL_TIM_OCPOLARITY_HIGH; + TIM_OC_InitStruct->OCNPolarity = LL_TIM_OCPOLARITY_HIGH; + TIM_OC_InitStruct->OCIdleState = LL_TIM_OCIDLESTATE_LOW; + TIM_OC_InitStruct->OCNIdleState = LL_TIM_OCIDLESTATE_LOW; +} + +/** + * @brief Configure the TIMx output channel. + * @param TIMx Timer Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH4 + * @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration + * data structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx output channel is initialized + * - ERROR: TIMx output channel is not initialized + */ +ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct) +{ + ErrorStatus result = ERROR; + + switch (Channel) + { + case LL_TIM_CHANNEL_CH1: + result = OC1Config(TIMx, TIM_OC_InitStruct); + break; + case LL_TIM_CHANNEL_CH2: + result = OC2Config(TIMx, TIM_OC_InitStruct); + break; + case LL_TIM_CHANNEL_CH3: + result = OC3Config(TIMx, TIM_OC_InitStruct); + break; + case LL_TIM_CHANNEL_CH4: + result = OC4Config(TIMx, TIM_OC_InitStruct); + break; + default: + break; + } + + return result; +} + +/** + * @brief Set the fields of the TIMx input channel configuration data + * structure to their default values. + * @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration + * data structure) + * @retval None + */ +void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) +{ + /* Set the default configuration */ + TIM_ICInitStruct->ICPolarity = LL_TIM_IC_POLARITY_RISING; + TIM_ICInitStruct->ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + TIM_ICInitStruct->ICPrescaler = LL_TIM_ICPSC_DIV1; + TIM_ICInitStruct->ICFilter = LL_TIM_IC_FILTER_FDIV1; +} + +/** + * @brief Configure the TIMx input channel. + * @param TIMx Timer Instance + * @param Channel This parameter can be one of the following values: + * @arg @ref LL_TIM_CHANNEL_CH1 + * @arg @ref LL_TIM_CHANNEL_CH2 + * @arg @ref LL_TIM_CHANNEL_CH3 + * @arg @ref LL_TIM_CHANNEL_CH4 + * @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data + * structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx output channel is initialized + * - ERROR: TIMx output channel is not initialized + */ +ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct) +{ + ErrorStatus result = ERROR; + + switch (Channel) + { + case LL_TIM_CHANNEL_CH1: + result = IC1Config(TIMx, TIM_IC_InitStruct); + break; + case LL_TIM_CHANNEL_CH2: + result = IC2Config(TIMx, TIM_IC_InitStruct); + break; + case LL_TIM_CHANNEL_CH3: + result = IC3Config(TIMx, TIM_IC_InitStruct); + break; + case LL_TIM_CHANNEL_CH4: + result = IC4Config(TIMx, TIM_IC_InitStruct); + break; + default: + break; + } + + return result; +} + +/** + * @brief Fills each TIM_EncoderInitStruct field with its default value + * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface + * configuration data structure) + * @retval None + */ +void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct) +{ + /* Set the default configuration */ + TIM_EncoderInitStruct->EncoderMode = LL_TIM_ENCODERMODE_X2_TI1; + TIM_EncoderInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING; + TIM_EncoderInitStruct->IC1ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + TIM_EncoderInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1; + TIM_EncoderInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1; + TIM_EncoderInitStruct->IC2Polarity = LL_TIM_IC_POLARITY_RISING; + TIM_EncoderInitStruct->IC2ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI; + TIM_EncoderInitStruct->IC2Prescaler = LL_TIM_ICPSC_DIV1; + TIM_EncoderInitStruct->IC2Filter = LL_TIM_IC_FILTER_FDIV1; +} + +/** + * @brief Configure the encoder interface of the timer instance. + * @param TIMx Timer Instance + * @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface + * configuration data structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, const LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct) +{ + uint32_t tmpccmr1; + uint32_t tmpccer; + + /* Check the parameters */ + assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_ENCODERMODE(TIM_EncoderInitStruct->EncoderMode)); + assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC1Polarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC1ActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC1Prescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC1Filter)); + assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC2Polarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC2ActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC2Prescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC2Filter)); + + /* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */ + TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Configure TI1 */ + tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1ActiveInput >> 16U); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Filter >> 16U); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Prescaler >> 16U); + + /* Configure TI2 */ + tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2ActiveInput >> 8U); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Filter >> 8U); + tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Prescaler >> 8U); + + /* Set TI1 and TI2 polarity and enable TI1 and TI2 */ + tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC1Polarity); + tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC2Polarity << 4U); + tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E); + + /* Set encoder mode */ + LL_TIM_SetEncoderMode(TIMx, TIM_EncoderInitStruct->EncoderMode); + + /* Write to TIMx CCMR1 */ + LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + +/** + * @brief Set the fields of the TIMx Hall sensor interface configuration data + * structure to their default values. + * @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (HALL sensor interface + * configuration data structure) + * @retval None + */ +void LL_TIM_HALLSENSOR_StructInit(LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct) +{ + /* Set the default configuration */ + TIM_HallSensorInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING; + TIM_HallSensorInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1; + TIM_HallSensorInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1; + TIM_HallSensorInitStruct->CommutationDelay = 0U; +} + +/** + * @brief Configure the Hall sensor interface of the timer instance. + * @note TIMx CH1, CH2 and CH3 inputs connected through a XOR + * to the TI1 input channel + * @note TIMx slave mode controller is configured in reset mode. + Selected internal trigger is TI1F_ED. + * @note Channel 1 is configured as input, IC1 is mapped on TRC. + * @note Captured value stored in TIMx_CCR1 correspond to the time elapsed + * between 2 changes on the inputs. It gives information about motor speed. + * @note Channel 2 is configured in output PWM 2 mode. + * @note Compare value stored in TIMx_CCR2 corresponds to the commutation delay. + * @note OC2REF is selected as trigger output on TRGO. + * @note LL_TIM_IC_POLARITY_BOTHEDGE must not be used for TI1 when it is used + * when TIMx operates in Hall sensor interface mode. + * @param TIMx Timer Instance + * @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (TIMx HALL sensor + * interface configuration data structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, const LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct) +{ + uint32_t tmpcr2; + uint32_t tmpccmr1; + uint32_t tmpccer; + uint32_t tmpsmcr; + + /* Check the parameters */ + assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_HallSensorInitStruct->IC1Polarity)); + assert_param(IS_LL_TIM_ICPSC(TIM_HallSensorInitStruct->IC1Prescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_HallSensorInitStruct->IC1Filter)); + + /* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */ + TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E); + + /* Get the TIMx CR2 register value */ + tmpcr2 = LL_TIM_ReadReg(TIMx, CR2); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx SMCR register value */ + tmpsmcr = LL_TIM_ReadReg(TIMx, SMCR); + + /* Connect TIMx_CH1, CH2 and CH3 pins to the TI1 input */ + tmpcr2 |= TIM_CR2_TI1S; + + /* OC2REF signal is used as trigger output (TRGO) */ + tmpcr2 |= LL_TIM_TRGO_OC2REF; + + /* Configure the slave mode controller */ + tmpsmcr &= (uint32_t)~(TIM_SMCR_TS | TIM_SMCR_SMS); + tmpsmcr |= LL_TIM_TS_TI1F_ED; + tmpsmcr |= LL_TIM_SLAVEMODE_RESET; + + /* Configure input channel 1 */ + tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC); + tmpccmr1 |= (uint32_t)(LL_TIM_ACTIVEINPUT_TRC >> 16U); + tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Filter >> 16U); + tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Prescaler >> 16U); + + /* Configure input channel 2 */ + tmpccmr1 &= (uint32_t)~(TIM_CCMR1_OC2M | TIM_CCMR1_OC2FE | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2CE); + tmpccmr1 |= (uint32_t)(LL_TIM_OCMODE_PWM2 << 8U); + + /* Set Channel 1 polarity and enable Channel 1 and Channel2 */ + tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP); + tmpccer |= (uint32_t)(TIM_HallSensorInitStruct->IC1Polarity); + tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E); + + /* Write to TIMx CR2 */ + LL_TIM_WriteReg(TIMx, CR2, tmpcr2); + + /* Write to TIMx SMCR */ + LL_TIM_WriteReg(TIMx, SMCR, tmpsmcr); + + /* Write to TIMx CCMR1 */ + LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + /* Write to TIMx CCR2 */ + LL_TIM_OC_SetCompareCH2(TIMx, TIM_HallSensorInitStruct->CommutationDelay); + + return SUCCESS; +} + +/** + * @brief Set the fields of the Break and Dead Time configuration data structure + * to their default values. + * @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration + * data structure) + * @retval None + */ +void LL_TIM_BDTR_StructInit(LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct) +{ + /* Set the default configuration */ + TIM_BDTRInitStruct->OSSRState = LL_TIM_OSSR_DISABLE; + TIM_BDTRInitStruct->OSSIState = LL_TIM_OSSI_DISABLE; + TIM_BDTRInitStruct->LockLevel = LL_TIM_LOCKLEVEL_OFF; + TIM_BDTRInitStruct->DeadTime = (uint8_t)0x00; + TIM_BDTRInitStruct->BreakState = LL_TIM_BREAK_DISABLE; + TIM_BDTRInitStruct->BreakPolarity = LL_TIM_BREAK_POLARITY_LOW; + TIM_BDTRInitStruct->AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE; +} + +/** + * @brief Configure the Break and Dead Time feature of the timer instance. + * @note As the bits AOE, BKP, BKE, OSSR, OSSI and DTG[7:0] can be write-locked + * depending on the LOCK configuration, it can be necessary to configure all of + * them during the first write access to the TIMx_BDTR register. + * @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not + * a timer instance provides a break input. + * @param TIMx Timer Instance + * @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration + * data structure) + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Break and Dead Time is initialized + * - ERROR: not applicable + */ +ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, const LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct) +{ + uint32_t tmpbdtr = 0; + + /* Check the parameters */ + assert_param(IS_TIM_BREAK_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_OSSR_STATE(TIM_BDTRInitStruct->OSSRState)); + assert_param(IS_LL_TIM_OSSI_STATE(TIM_BDTRInitStruct->OSSIState)); + assert_param(IS_LL_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->LockLevel)); + assert_param(IS_LL_TIM_BREAK_STATE(TIM_BDTRInitStruct->BreakState)); + assert_param(IS_LL_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->BreakPolarity)); + assert_param(IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->AutomaticOutput)); + + /* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State, + the OSSI State, the dead time value and the Automatic Output Enable Bit */ + + /* Set the BDTR bits */ + MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, TIM_BDTRInitStruct->DeadTime); + MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, TIM_BDTRInitStruct->LockLevel); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, TIM_BDTRInitStruct->OSSIState); + MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, TIM_BDTRInitStruct->OSSRState); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, TIM_BDTRInitStruct->BreakState); + MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, TIM_BDTRInitStruct->BreakPolarity); + MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, TIM_BDTRInitStruct->AutomaticOutput); + MODIFY_REG(tmpbdtr, TIM_BDTR_MOE, TIM_BDTRInitStruct->AutomaticOutput); + + /* Set TIMx_BDTR */ + LL_TIM_WriteReg(TIMx, BDTR, tmpbdtr); + + return SUCCESS; +} +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup TIM_LL_Private_Functions TIM Private Functions + * @brief Private functions + * @{ + */ +/** + * @brief Configure the TIMx output channel 1. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 1 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC1Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr1; + uint32_t tmpccer; + uint32_t tmpcr2; + + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity)); + + /* Disable the Channel 1: Reset the CC1E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC1E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CR2 register value */ + tmpcr2 = LL_TIM_ReadReg(TIMx, CR2); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1); + + /* Reset Capture/Compare selection Bits */ + CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC1S); + + /* Set the Output Compare Mode */ + MODIFY_REG(tmpccmr1, TIM_CCMR1_OC1M, TIM_OCInitStruct->OCMode); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC1P, TIM_OCInitStruct->OCPolarity); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC1E, TIM_OCInitStruct->OCState); + + if (IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState)); + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState)); + + /* Set the complementary output Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC1NP, TIM_OCInitStruct->OCNPolarity << 2U); + + /* Set the complementary output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC1NE, TIM_OCInitStruct->OCNState << 2U); + + /* Set the Output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS1, TIM_OCInitStruct->OCIdleState); + + /* Set the complementary output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS1N, TIM_OCInitStruct->OCNIdleState << 1U); + } + + /* Write to TIMx CR2 */ + LL_TIM_WriteReg(TIMx, CR2, tmpcr2); + + /* Write to TIMx CCMR1 */ + LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH1(TIMx, TIM_OCInitStruct->CompareValue); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx output channel 2. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 2 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC2Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr1; + uint32_t tmpccer; + uint32_t tmpcr2; + + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity)); + + /* Disable the Channel 2: Reset the CC2E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC2E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CR2 register value */ + tmpcr2 = LL_TIM_ReadReg(TIMx, CR2); + + /* Get the TIMx CCMR1 register value */ + tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1); + + /* Reset Capture/Compare selection Bits */ + CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC2S); + + /* Select the Output Compare Mode */ + MODIFY_REG(tmpccmr1, TIM_CCMR1_OC2M, TIM_OCInitStruct->OCMode << 8U); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC2P, TIM_OCInitStruct->OCPolarity << 4U); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC2E, TIM_OCInitStruct->OCState << 4U); + + if (IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState)); + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState)); + + /* Set the complementary output Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC2NP, TIM_OCInitStruct->OCNPolarity << 6U); + + /* Set the complementary output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC2NE, TIM_OCInitStruct->OCNState << 6U); + + /* Set the Output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS2, TIM_OCInitStruct->OCIdleState << 2U); + + /* Set the complementary output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS2N, TIM_OCInitStruct->OCNIdleState << 3U); + } + + /* Write to TIMx CR2 */ + LL_TIM_WriteReg(TIMx, CR2, tmpcr2); + + /* Write to TIMx CCMR1 */ + LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH2(TIMx, TIM_OCInitStruct->CompareValue); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx output channel 3. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 3 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC3Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr2; + uint32_t tmpccer; + uint32_t tmpcr2; + + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity)); + + /* Disable the Channel 3: Reset the CC3E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC3E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CR2 register value */ + tmpcr2 = LL_TIM_ReadReg(TIMx, CR2); + + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2); + + /* Reset Capture/Compare selection Bits */ + CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC3S); + + /* Select the Output Compare Mode */ + MODIFY_REG(tmpccmr2, TIM_CCMR2_OC3M, TIM_OCInitStruct->OCMode); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC3P, TIM_OCInitStruct->OCPolarity << 8U); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC3E, TIM_OCInitStruct->OCState << 8U); + + if (IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState)); + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState)); + + /* Set the complementary output Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC3NP, TIM_OCInitStruct->OCNPolarity << 10U); + + /* Set the complementary output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC3NE, TIM_OCInitStruct->OCNState << 10U); + + /* Set the Output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS3, TIM_OCInitStruct->OCIdleState << 4U); + + /* Set the complementary output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS3N, TIM_OCInitStruct->OCNIdleState << 5U); + } + + /* Write to TIMx CR2 */ + LL_TIM_WriteReg(TIMx, CR2, tmpcr2); + + /* Write to TIMx CCMR2 */ + LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH3(TIMx, TIM_OCInitStruct->CompareValue); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx output channel 4. + * @param TIMx Timer Instance + * @param TIM_OCInitStruct pointer to the the TIMx output channel 4 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus OC4Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct) +{ + uint32_t tmpccmr2; + uint32_t tmpccer; + uint32_t tmpcr2; + + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity)); + assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity)); + assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState)); + + /* Disable the Channel 4: Reset the CC4E Bit */ + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC4E); + + /* Get the TIMx CCER register value */ + tmpccer = LL_TIM_ReadReg(TIMx, CCER); + + /* Get the TIMx CR2 register value */ + tmpcr2 = LL_TIM_ReadReg(TIMx, CR2); + + /* Get the TIMx CCMR2 register value */ + tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2); + + /* Reset Capture/Compare selection Bits */ + CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC4S); + + /* Select the Output Compare Mode */ + MODIFY_REG(tmpccmr2, TIM_CCMR2_OC4M, TIM_OCInitStruct->OCMode << 8U); + + /* Set the Output Compare Polarity */ + MODIFY_REG(tmpccer, TIM_CCER_CC4P, TIM_OCInitStruct->OCPolarity << 12U); + + /* Set the Output State */ + MODIFY_REG(tmpccer, TIM_CCER_CC4E, TIM_OCInitStruct->OCState << 12U); + + if (IS_TIM_BREAK_INSTANCE(TIMx)) + { + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState)); + assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState)); + + /* Set the Output Idle state */ + MODIFY_REG(tmpcr2, TIM_CR2_OIS4, TIM_OCInitStruct->OCIdleState << 6U); + } + + /* Write to TIMx CR2 */ + LL_TIM_WriteReg(TIMx, CR2, tmpcr2); + + /* Write to TIMx CCMR2 */ + LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2); + + /* Set the Capture Compare Register value */ + LL_TIM_OC_SetCompareCH4(TIMx, TIM_OCInitStruct->CompareValue); + + /* Write to TIMx CCER */ + LL_TIM_WriteReg(TIMx, CCER, tmpccer); + + return SUCCESS; +} + + +/** + * @brief Configure the TIMx input channel 1. + * @param TIMx Timer Instance + * @param TIM_ICInitStruct pointer to the the TIMx input channel 1 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus IC1Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC1_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter)); + + /* Disable the Channel 1: Reset the CC1E Bit */ + TIMx->CCER &= (uint32_t)~TIM_CCER_CC1E; + + /* Select the Input and set the filter and the prescaler value */ + MODIFY_REG(TIMx->CCMR1, + (TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC), + (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U); + + /* Select the Polarity and set the CC1E Bit */ + MODIFY_REG(TIMx->CCER, + (TIM_CCER_CC1P | TIM_CCER_CC1NP), + (TIM_ICInitStruct->ICPolarity | TIM_CCER_CC1E)); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx input channel 2. + * @param TIMx Timer Instance + * @param TIM_ICInitStruct pointer to the the TIMx input channel 2 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus IC2Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC2_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter)); + + /* Disable the Channel 2: Reset the CC2E Bit */ + TIMx->CCER &= (uint32_t)~TIM_CCER_CC2E; + + /* Select the Input and set the filter and the prescaler value */ + MODIFY_REG(TIMx->CCMR1, + (TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC), + (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U); + + /* Select the Polarity and set the CC2E Bit */ + MODIFY_REG(TIMx->CCER, + (TIM_CCER_CC2P | TIM_CCER_CC2NP), + ((TIM_ICInitStruct->ICPolarity << 4U) | TIM_CCER_CC2E)); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx input channel 3. + * @param TIMx Timer Instance + * @param TIM_ICInitStruct pointer to the the TIMx input channel 3 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus IC3Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC3_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter)); + + /* Disable the Channel 3: Reset the CC3E Bit */ + TIMx->CCER &= (uint32_t)~TIM_CCER_CC3E; + + /* Select the Input and set the filter and the prescaler value */ + MODIFY_REG(TIMx->CCMR2, + (TIM_CCMR2_CC3S | TIM_CCMR2_IC3F | TIM_CCMR2_IC3PSC), + (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U); + + /* Select the Polarity and set the CC3E Bit */ + MODIFY_REG(TIMx->CCER, + (TIM_CCER_CC3P | TIM_CCER_CC3NP), + ((TIM_ICInitStruct->ICPolarity << 8U) | TIM_CCER_CC3E)); + + return SUCCESS; +} + +/** + * @brief Configure the TIMx input channel 4. + * @param TIMx Timer Instance + * @param TIM_ICInitStruct pointer to the the TIMx input channel 4 configuration data structure + * @retval An ErrorStatus enumeration value: + * - SUCCESS: TIMx registers are de-initialized + * - ERROR: not applicable + */ +static ErrorStatus IC4Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct) +{ + /* Check the parameters */ + assert_param(IS_TIM_CC4_INSTANCE(TIMx)); + assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity)); + assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput)); + assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler)); + assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter)); + + /* Disable the Channel 4: Reset the CC4E Bit */ + TIMx->CCER &= (uint32_t)~TIM_CCER_CC4E; + + /* Select the Input and set the filter and the prescaler value */ + MODIFY_REG(TIMx->CCMR2, + (TIM_CCMR2_CC4S | TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC), + (TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U); + + /* Select the Polarity and set the CC2E Bit */ + MODIFY_REG(TIMx->CCER, + (TIM_CCER_CC4P | TIM_CCER_CC4NP), + ((TIM_ICInitStruct->ICPolarity << 12U) | TIM_CCER_CC4E)); + + return SUCCESS; +} + + +/** + * @} + */ + +/** + * @} + */ + +#endif /* TIM1 || TIM2 || TIM3 || TIM4 || TIM5 || TIM6 || TIM7 || TIM8 || TIM9 || TIM10 || TIM11 || TIM12 || TIM13 || TIM14 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c new file mode 100644 index 0000000..5b1ffa8 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c @@ -0,0 +1,500 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_usart.c + * @author MCD Application Team + * @brief USART LL module driver. + ****************************************************************************** + * @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. + * + ****************************************************************************** + */ + +#if defined(USE_FULL_LL_DRIVER) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_usart.h" +#include "stm32f4xx_ll_rcc.h" +#include "stm32f4xx_ll_bus.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +#if defined (USART1) || defined (USART2) || defined (USART3) || defined (USART6) || defined (UART4) || defined (UART5) || defined (UART7) || defined (UART8) || defined (UART9) || defined (UART10) + +/** @addtogroup USART_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup USART_LL_Private_Constants + * @{ + */ + +/** + * @} + */ + + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup USART_LL_Private_Macros + * @{ + */ + +/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available + * divided by the smallest oversampling used on the USART (i.e. 8) */ +#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 12500000U) + +/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */ +#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U) + +#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \ + || ((__VALUE__) == LL_USART_DIRECTION_RX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX) \ + || ((__VALUE__) == LL_USART_DIRECTION_TX_RX)) + +#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \ + || ((__VALUE__) == LL_USART_PARITY_EVEN) \ + || ((__VALUE__) == LL_USART_PARITY_ODD)) + +#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_8B) \ + || ((__VALUE__) == LL_USART_DATAWIDTH_9B)) + +#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \ + || ((__VALUE__) == LL_USART_OVERSAMPLING_8)) + +#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \ + || ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT)) + +#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \ + || ((__VALUE__) == LL_USART_PHASE_2EDGE)) + +#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \ + || ((__VALUE__) == LL_USART_POLARITY_HIGH)) + +#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \ + || ((__VALUE__) == LL_USART_CLOCK_ENABLE)) + +#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_1) \ + || ((__VALUE__) == LL_USART_STOPBITS_1_5) \ + || ((__VALUE__) == LL_USART_STOPBITS_2)) + +#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_CTS) \ + || ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS)) + +/** + * @} + */ + +/* Private function prototypes -----------------------------------------------*/ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup USART_LL_Exported_Functions + * @{ + */ + +/** @addtogroup USART_LL_EF_Init + * @{ + */ + +/** + * @brief De-initialize USART registers (Registers restored to their default values). + * @param USARTx USART Instance + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are de-initialized + * - ERROR: USART registers are not de-initialized + */ +ErrorStatus LL_USART_DeInit(const USART_TypeDef *USARTx) +{ + ErrorStatus status = SUCCESS; + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + + if (USARTx == USART1) + { + /* Force reset of USART clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART1); + + /* Release reset of USART clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART1); + } + else if (USARTx == USART2) + { + /* Force reset of USART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART2); + + /* Release reset of USART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART2); + } +#if defined(USART3) + else if (USARTx == USART3) + { + /* Force reset of USART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART3); + + /* Release reset of USART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART3); + } +#endif /* USART3 */ +#if defined(USART6) + else if (USARTx == USART6) + { + /* Force reset of USART clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART6); + + /* Release reset of USART clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART6); + } +#endif /* USART6 */ +#if defined(UART4) + else if (USARTx == UART4) + { + /* Force reset of UART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART4); + + /* Release reset of UART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART4); + } +#endif /* UART4 */ +#if defined(UART5) + else if (USARTx == UART5) + { + /* Force reset of UART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART5); + + /* Release reset of UART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART5); + } +#endif /* UART5 */ +#if defined(UART7) + else if (USARTx == UART7) + { + /* Force reset of UART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART7); + + /* Release reset of UART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART7); + } +#endif /* UART7 */ +#if defined(UART8) + else if (USARTx == UART8) + { + /* Force reset of UART clock */ + LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART8); + + /* Release reset of UART clock */ + LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART8); + } +#endif /* UART8 */ +#if defined(UART9) + else if (USARTx == UART9) + { + /* Force reset of UART clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_UART9); + + /* Release reset of UART clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_UART9); + } +#endif /* UART9 */ +#if defined(UART10) + else if (USARTx == UART10) + { + /* Force reset of UART clock */ + LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_UART10); + + /* Release reset of UART clock */ + LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_UART10); + } +#endif /* UART10 */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Initialize USART registers according to the specified + * parameters in USART_InitStruct. + * @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0), + * USART IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0). + * @param USARTx USART Instance + * @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure + * that contains the configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers are initialized according to USART_InitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, const LL_USART_InitTypeDef *USART_InitStruct) +{ + ErrorStatus status = ERROR; + uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO; + LL_RCC_ClocksTypeDef rcc_clocks; + + /* Check the parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate)); + assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth)); + assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits)); + assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity)); + assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection)); + assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl)); + assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling)); + + /* USART needs to be in disabled state, in order to be able to configure some bits in + CRx registers */ + if (LL_USART_IsEnabled(USARTx) == 0U) + { + /*---------------------------- USART CR1 Configuration ----------------------- + * Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters: + * - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value + * - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value + * - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value + * - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value. + */ + MODIFY_REG(USARTx->CR1, + (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8), + (USART_InitStruct->DataWidth | USART_InitStruct->Parity | + USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling)); + + /*---------------------------- USART CR2 Configuration ----------------------- + * Configure USARTx CR2 (Stop bits) with parameters: + * - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value. + * - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit(). + */ + LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits); + + /*---------------------------- USART CR3 Configuration ----------------------- + * Configure USARTx CR3 (Hardware Flow Control) with parameters: + * - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to USART_InitStruct->HardwareFlowControl value. + */ + LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl); + + /*---------------------------- USART BRR Configuration ----------------------- + * Retrieve Clock frequency used for USART Peripheral + */ + LL_RCC_GetSystemClocksFreq(&rcc_clocks); + if (USARTx == USART1) + { + periphclk = rcc_clocks.PCLK2_Frequency; + } + else if (USARTx == USART2) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#if defined(USART3) + else if (USARTx == USART3) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#endif /* USART3 */ +#if defined(USART6) + else if (USARTx == USART6) + { + periphclk = rcc_clocks.PCLK2_Frequency; + } +#endif /* USART6 */ +#if defined(UART4) + else if (USARTx == UART4) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#endif /* UART4 */ +#if defined(UART5) + else if (USARTx == UART5) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#endif /* UART5 */ +#if defined(UART7) + else if (USARTx == UART7) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#endif /* UART7 */ +#if defined(UART8) + else if (USARTx == UART8) + { + periphclk = rcc_clocks.PCLK1_Frequency; + } +#endif /* UART8 */ +#if defined(UART9) + else if (USARTx == UART9) + { + periphclk = rcc_clocks.PCLK2_Frequency; + } +#endif /* UART9 */ +#if defined(UART10) + else if (USARTx == UART10) + { + periphclk = rcc_clocks.PCLK2_Frequency; + } +#endif /* UART10 */ + else + { + /* Nothing to do, as error code is already assigned to ERROR value */ + } + + /* Configure the USART Baud Rate : + - valid baud rate value (different from 0) is required + - Peripheral clock as returned by RCC service, should be valid (different from 0). + */ + if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO) + && (USART_InitStruct->BaudRate != 0U)) + { + status = SUCCESS; + LL_USART_SetBaudRate(USARTx, + periphclk, + USART_InitStruct->OverSampling, + USART_InitStruct->BaudRate); + + /* Check BRR is greater than or equal to 16d */ + assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR)); + } + } + /* Endif (=> USART not in Disabled state => return ERROR) */ + + return (status); +} + +/** + * @brief Set each @ref LL_USART_InitTypeDef field to default value. + * @param USART_InitStruct Pointer to a @ref LL_USART_InitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ + +void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct) +{ + /* Set USART_InitStruct fields to default values */ + USART_InitStruct->BaudRate = 9600U; + USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B; + USART_InitStruct->StopBits = LL_USART_STOPBITS_1; + USART_InitStruct->Parity = LL_USART_PARITY_NONE ; + USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX; + USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE; + USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16; +} + +/** + * @brief Initialize USART Clock related settings according to the + * specified parameters in the USART_ClockInitStruct. + * @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0), + * USART IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned. + * @param USARTx USART Instance + * @param USART_ClockInitStruct Pointer to a @ref LL_USART_ClockInitTypeDef structure + * that contains the Clock configuration information for the specified USART peripheral. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: USART registers related to Clock settings are initialized according to USART_ClockInitStruct content + * - ERROR: Problem occurred during USART Registers initialization + */ +ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, const LL_USART_ClockInitTypeDef *USART_ClockInitStruct) +{ + ErrorStatus status = SUCCESS; + + /* Check USART Instance and Clock signal output parameters */ + assert_param(IS_UART_INSTANCE(USARTx)); + assert_param(IS_LL_USART_CLOCKOUTPUT(USART_ClockInitStruct->ClockOutput)); + + /* USART needs to be in disabled state, in order to be able to configure some bits in + CRx registers */ + if (LL_USART_IsEnabled(USARTx) == 0U) + { + /*---------------------------- USART CR2 Configuration -----------------------*/ + /* If Clock signal has to be output */ + if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE) + { + /* Deactivate Clock signal delivery : + * - Disable Clock Output: USART_CR2_CLKEN cleared + */ + LL_USART_DisableSCLKOutput(USARTx); + } + else + { + /* Ensure USART instance is USART capable */ + assert_param(IS_USART_INSTANCE(USARTx)); + + /* Check clock related parameters */ + assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity)); + assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase)); + assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse)); + + /*---------------------------- USART CR2 Configuration ----------------------- + * Configure USARTx CR2 (Clock signal related bits) with parameters: + * - Enable Clock Output: USART_CR2_CLKEN set + * - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value + * - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value + * - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value. + */ + MODIFY_REG(USARTx->CR2, + USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL, + USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity | + USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse); + } + } + /* Else (USART not in Disabled state => return ERROR */ + else + { + status = ERROR; + } + + return (status); +} + +/** + * @brief Set each field of a @ref LL_USART_ClockInitTypeDef type structure to default value. + * @param USART_ClockInitStruct Pointer to a @ref LL_USART_ClockInitTypeDef structure + * whose fields will be set to default values. + * @retval None + */ +void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct) +{ + /* Set LL_USART_ClockInitStruct fields with default values */ + USART_ClockInitStruct->ClockOutput = LL_USART_CLOCK_DISABLE; + USART_ClockInitStruct->ClockPolarity = LL_USART_POLARITY_LOW; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */ + USART_ClockInitStruct->ClockPhase = LL_USART_PHASE_1EDGE; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */ + USART_ClockInitStruct->LastBitClockPulse = LL_USART_LASTCLKPULSE_NO_OUTPUT; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */ +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* USART1 || USART2 || USART3 || USART6 || UART4 || UART5 || UART7 || UART8 || UART9 || UART10 */ + +/** + * @} + */ + +#endif /* USE_FULL_LL_DRIVER */ + + diff --git a/libs/hal/stm32f4xx_ll_usb.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c similarity index 99% rename from libs/hal/stm32f4xx_ll_usb.c rename to libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c index 1df5fcf..59c83e1 100644 --- a/libs/hal/stm32f4xx_ll_usb.c +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c @@ -346,9 +346,6 @@ HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cf /* Restart the Phy Clock */ USBx_PCGCCTL = 0U; - /* Device mode configuration */ - USBx_DEVICE->DCFG |= DCFG_FRAME_INTERVAL_80; - if (cfg.phy_itface == USB_OTG_ULPI_PHY) { if (cfg.speed == USBD_HS_SPEED) @@ -1380,7 +1377,7 @@ uint32_t USB_ReadDevInEPInterrupt(USB_OTG_GlobalTypeDef *USBx, uint8_t epnum) */ void USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt) { - USBx->GINTSTS |= interrupt; + USBx->GINTSTS &= interrupt; } /** diff --git a/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c new file mode 100644 index 0000000..34df6ea --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c @@ -0,0 +1,749 @@ +/** + ****************************************************************************** + * @file stm32f4xx_ll_utils.c + * @author MCD Application Team + * @brief UTILS LL module driver. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 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. + * + ****************************************************************************** + */ +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_ll_utils.h" +#include "stm32f4xx_ll_rcc.h" +#include "stm32f4xx_ll_system.h" +#include "stm32f4xx_ll_pwr.h" +#ifdef USE_FULL_ASSERT +#include "stm32_assert.h" +#else +#define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +/** @addtogroup STM32F4xx_LL_Driver + * @{ + */ + +/** @addtogroup UTILS_LL + * @{ + */ + +/* Private types -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private constants ---------------------------------------------------------*/ +/** @addtogroup UTILS_LL_Private_Constants + * @{ + */ +#if defined(RCC_MAX_FREQUENCY_SCALE1) +#define UTILS_MAX_FREQUENCY_SCALE1 RCC_MAX_FREQUENCY /*!< Maximum frequency for system clock at power scale1, in Hz */ +#endif /*RCC_MAX_FREQUENCY_SCALE1 */ +#define UTILS_MAX_FREQUENCY_SCALE2 RCC_MAX_FREQUENCY_SCALE2 /*!< Maximum frequency for system clock at power scale2, in Hz */ +#if defined(RCC_MAX_FREQUENCY_SCALE3) +#define UTILS_MAX_FREQUENCY_SCALE3 RCC_MAX_FREQUENCY_SCALE3 /*!< Maximum frequency for system clock at power scale3, in Hz */ +#endif /* MAX_FREQUENCY_SCALE3 */ + +/* Defines used for PLL range */ +#define UTILS_PLLVCO_INPUT_MIN RCC_PLLVCO_INPUT_MIN /*!< Frequency min for PLLVCO input, in Hz */ +#define UTILS_PLLVCO_INPUT_MAX RCC_PLLVCO_INPUT_MAX /*!< Frequency max for PLLVCO input, in Hz */ +#define UTILS_PLLVCO_OUTPUT_MIN RCC_PLLVCO_OUTPUT_MIN /*!< Frequency min for PLLVCO output, in Hz */ +#define UTILS_PLLVCO_OUTPUT_MAX RCC_PLLVCO_OUTPUT_MAX /*!< Frequency max for PLLVCO output, in Hz */ + +/* Defines used for HSE range */ +#define UTILS_HSE_FREQUENCY_MIN 4000000U /*!< Frequency min for HSE frequency, in Hz */ +#define UTILS_HSE_FREQUENCY_MAX 26000000U /*!< Frequency max for HSE frequency, in Hz */ + +/* Defines used for FLASH latency according to HCLK Frequency */ +#if defined(FLASH_SCALE1_LATENCY1_FREQ) +#define UTILS_SCALE1_LATENCY1_FREQ FLASH_SCALE1_LATENCY1_FREQ /*!< HCLK frequency to set FLASH latency 1 in power scale 1 */ +#endif +#if defined(FLASH_SCALE1_LATENCY2_FREQ) +#define UTILS_SCALE1_LATENCY2_FREQ FLASH_SCALE1_LATENCY2_FREQ /*!< HCLK frequency to set FLASH latency 2 in power scale 1 */ +#endif +#if defined(FLASH_SCALE1_LATENCY3_FREQ) +#define UTILS_SCALE1_LATENCY3_FREQ FLASH_SCALE1_LATENCY3_FREQ /*!< HCLK frequency to set FLASH latency 3 in power scale 1 */ +#endif +#if defined(FLASH_SCALE1_LATENCY4_FREQ) +#define UTILS_SCALE1_LATENCY4_FREQ FLASH_SCALE1_LATENCY4_FREQ /*!< HCLK frequency to set FLASH latency 4 in power scale 1 */ +#endif +#if defined(FLASH_SCALE1_LATENCY5_FREQ) +#define UTILS_SCALE1_LATENCY5_FREQ FLASH_SCALE1_LATENCY5_FREQ /*!< HCLK frequency to set FLASH latency 5 in power scale 1 */ +#endif +#define UTILS_SCALE2_LATENCY1_FREQ FLASH_SCALE2_LATENCY1_FREQ /*!< HCLK frequency to set FLASH latency 1 in power scale 2 */ +#define UTILS_SCALE2_LATENCY2_FREQ FLASH_SCALE2_LATENCY2_FREQ /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */ +#if defined(FLASH_SCALE2_LATENCY3_FREQ) +#define UTILS_SCALE2_LATENCY3_FREQ FLASH_SCALE2_LATENCY3_FREQ /*!< HCLK frequency to set FLASH latency 2 in power scale 2 */ +#endif +#if defined(FLASH_SCALE2_LATENCY4_FREQ) +#define UTILS_SCALE2_LATENCY4_FREQ FLASH_SCALE2_LATENCY4_FREQ /*!< HCLK frequency to set FLASH latency 4 in power scale 2 */ +#endif +#if defined(FLASH_SCALE2_LATENCY5_FREQ) +#define UTILS_SCALE2_LATENCY5_FREQ FLASH_SCALE2_LATENCY5_FREQ /*!< HCLK frequency to set FLASH latency 5 in power scale 2 */ +#endif +#if defined(FLASH_SCALE3_LATENCY1_FREQ) +#define UTILS_SCALE3_LATENCY1_FREQ FLASH_SCALE3_LATENCY1_FREQ /*!< HCLK frequency to set FLASH latency 1 in power scale 3 */ +#endif +#if defined(FLASH_SCALE3_LATENCY2_FREQ) +#define UTILS_SCALE3_LATENCY2_FREQ FLASH_SCALE3_LATENCY2_FREQ /*!< HCLK frequency to set FLASH latency 2 in power scale 3 */ +#endif +#if defined(FLASH_SCALE3_LATENCY3_FREQ) +#define UTILS_SCALE3_LATENCY3_FREQ FLASH_SCALE3_LATENCY3_FREQ /*!< HCLK frequency to set FLASH latency 3 in power scale 3 */ +#endif +#if defined(FLASH_SCALE3_LATENCY4_FREQ) +#define UTILS_SCALE3_LATENCY4_FREQ FLASH_SCALE3_LATENCY4_FREQ /*!< HCLK frequency to set FLASH latency 4 in power scale 3 */ +#endif +#if defined(FLASH_SCALE3_LATENCY5_FREQ) +#define UTILS_SCALE3_LATENCY5_FREQ FLASH_SCALE3_LATENCY5_FREQ /*!< HCLK frequency to set FLASH latency 5 in power scale 3 */ +#endif +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @addtogroup UTILS_LL_Private_Macros + * @{ + */ +#define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \ + || ((__VALUE__) == LL_RCC_SYSCLK_DIV_512)) + +#define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \ + || ((__VALUE__) == LL_RCC_APB1_DIV_2) \ + || ((__VALUE__) == LL_RCC_APB1_DIV_4) \ + || ((__VALUE__) == LL_RCC_APB1_DIV_8) \ + || ((__VALUE__) == LL_RCC_APB1_DIV_16)) + +#define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \ + || ((__VALUE__) == LL_RCC_APB2_DIV_2) \ + || ((__VALUE__) == LL_RCC_APB2_DIV_4) \ + || ((__VALUE__) == LL_RCC_APB2_DIV_8) \ + || ((__VALUE__) == LL_RCC_APB2_DIV_16)) + +#define IS_LL_UTILS_PLLM_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLM_DIV_2) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_3) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_4) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_5) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_6) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_7) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_8) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_9) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_10) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_11) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_12) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_13) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_14) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_15) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_16) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_17) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_18) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_19) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_20) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_21) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_22) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_23) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_24) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_25) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_26) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_27) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_28) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_29) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_30) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_31) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_32) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_33) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_34) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_35) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_36) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_37) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_38) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_39) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_40) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_41) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_42) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_43) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_44) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_45) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_46) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_47) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_48) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_49) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_50) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_51) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_52) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_53) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_54) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_55) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_56) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_57) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_58) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_59) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_60) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_61) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_62) \ + || ((__VALUE__) == LL_RCC_PLLM_DIV_63)) + +#define IS_LL_UTILS_PLLN_VALUE(__VALUE__) ((RCC_PLLN_MIN_VALUE <= (__VALUE__)) && ((__VALUE__) <= RCC_PLLN_MAX_VALUE)) + +#define IS_LL_UTILS_PLLP_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLLP_DIV_2) \ + || ((__VALUE__) == LL_RCC_PLLP_DIV_4) \ + || ((__VALUE__) == LL_RCC_PLLP_DIV_6) \ + || ((__VALUE__) == LL_RCC_PLLP_DIV_8)) + +#define IS_LL_UTILS_PLLVCO_INPUT(__VALUE__) ((UTILS_PLLVCO_INPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_INPUT_MAX)) + +#define IS_LL_UTILS_PLLVCO_OUTPUT(__VALUE__) ((UTILS_PLLVCO_OUTPUT_MIN <= (__VALUE__)) && ((__VALUE__) <= UTILS_PLLVCO_OUTPUT_MAX)) + +#if !defined(RCC_MAX_FREQUENCY_SCALE1) +#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2) : \ + ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE3)) + +#elif defined(RCC_MAX_FREQUENCY_SCALE3) +#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \ + (LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2) : \ + ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE3)) + +#else +#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) ? ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE1) : \ + ((__VALUE__) <= UTILS_MAX_FREQUENCY_SCALE2)) + +#endif /* RCC_MAX_FREQUENCY_SCALE1*/ +#define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \ + || ((__STATE__) == LL_UTILS_HSEBYPASS_OFF)) + +#define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX)) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup UTILS_LL_Private_Functions UTILS Private functions + * @{ + */ +static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, + LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct); +static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct); +static ErrorStatus UTILS_PLL_IsBusy(void); +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup UTILS_LL_Exported_Functions + * @{ + */ + +/** @addtogroup UTILS_LL_EF_DELAY + * @{ + */ + +/** + * @brief This function configures the Cortex-M SysTick source to have 1ms time base. + * @note When a RTOS is used, it is recommended to avoid changing the Systick + * configuration by calling this function, for a delay use rather osDelay RTOS service. + * @param HCLKFrequency HCLK frequency in Hz + * @note HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq + * @retval None + */ +void LL_Init1msTick(uint32_t HCLKFrequency) +{ + /* Use frequency provided in argument */ + LL_InitTick(HCLKFrequency, 1000U); +} + +/** + * @brief This function provides accurate delay (in milliseconds) based + * on SysTick counter flag + * @note When a RTOS is used, it is recommended to avoid using blocking delay + * and use rather osDelay service. + * @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which + * will configure Systick to 1ms + * @param Delay specifies the delay time length, in milliseconds. + * @retval None + */ +void LL_mDelay(uint32_t Delay) +{ + __IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */ + /* Add this code to indicate that local variable is not used */ + ((void)tmp); + + /* Add a period to guaranty minimum wait */ + if(Delay < LL_MAX_DELAY) + { + Delay++; + } + + while (Delay) + { + if((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U) + { + Delay--; + } + } +} + +/** + * @} + */ + +/** @addtogroup UTILS_EF_SYSTEM + * @brief System Configuration functions + * + @verbatim + =============================================================================== + ##### System Configuration functions ##### + =============================================================================== + [..] + System, AHB and APB buses clocks configuration + + (+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is 180000000 Hz. + @endverbatim + @internal + Depending on the device voltage range, the maximum frequency should be + adapted accordingly to the Refenece manual. + @endinternal + * @{ + */ + +/** + * @brief This function sets directly SystemCoreClock CMSIS variable. + * @note Variable can be calculated also through SystemCoreClockUpdate function. + * @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro) + * @retval None + */ +void LL_SetSystemCoreClock(uint32_t HCLKFrequency) +{ + /* HCLK clock frequency */ + SystemCoreClock = HCLKFrequency; +} + +/** + * @brief Update number of Flash wait states in line with new frequency and current + voltage range. + * @note This Function support ONLY devices with supply voltage (voltage range) between 2.7V and 3.6V + * @param HCLK_Frequency HCLK frequency + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Latency has been modified + * - ERROR: Latency cannot be modified + */ +ErrorStatus LL_SetFlashLatency(uint32_t HCLK_Frequency) +{ + uint32_t timeout; + uint32_t getlatency; + uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */ + ErrorStatus status = SUCCESS; + + + /* Frequency cannot be equal to 0 */ + if(HCLK_Frequency == 0U) + { + status = ERROR; + } + else + { + if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE1) + { +#if defined (UTILS_SCALE1_LATENCY5_FREQ) + if((HCLK_Frequency > UTILS_SCALE1_LATENCY5_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_5; + } +#endif /*UTILS_SCALE1_LATENCY5_FREQ */ +#if defined (UTILS_SCALE1_LATENCY4_FREQ) + if((HCLK_Frequency > UTILS_SCALE1_LATENCY4_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_4; + } +#endif /* UTILS_SCALE1_LATENCY4_FREQ */ +#if defined (UTILS_SCALE1_LATENCY3_FREQ) + if((HCLK_Frequency > UTILS_SCALE1_LATENCY3_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_3; + } +#endif /* UTILS_SCALE1_LATENCY3_FREQ */ +#if defined (UTILS_SCALE1_LATENCY2_FREQ) + if((HCLK_Frequency > UTILS_SCALE1_LATENCY2_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_2; + } + else + { + if((HCLK_Frequency > UTILS_SCALE1_LATENCY1_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_1; + } + } +#endif /* UTILS_SCALE1_LATENCY2_FREQ */ + } + if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE2) + { +#if defined (UTILS_SCALE2_LATENCY5_FREQ) + if((HCLK_Frequency > UTILS_SCALE2_LATENCY5_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_5; + } +#endif /*UTILS_SCALE1_LATENCY5_FREQ */ +#if defined (UTILS_SCALE2_LATENCY4_FREQ) + if((HCLK_Frequency > UTILS_SCALE2_LATENCY4_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_4; + } +#endif /*UTILS_SCALE1_LATENCY4_FREQ */ +#if defined (UTILS_SCALE2_LATENCY3_FREQ) + if((HCLK_Frequency > UTILS_SCALE2_LATENCY3_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_3; + } +#endif /*UTILS_SCALE1_LATENCY3_FREQ */ + if((HCLK_Frequency > UTILS_SCALE2_LATENCY2_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_2; + } + else + { + if((HCLK_Frequency > UTILS_SCALE2_LATENCY1_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_1; + } + } + } +#if defined (LL_PWR_REGU_VOLTAGE_SCALE3) + if(LL_PWR_GetRegulVoltageScaling() == LL_PWR_REGU_VOLTAGE_SCALE3) + { +#if defined (UTILS_SCALE3_LATENCY3_FREQ) + if((HCLK_Frequency > UTILS_SCALE3_LATENCY3_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_3; + } +#endif /*UTILS_SCALE1_LATENCY3_FREQ */ +#if defined (UTILS_SCALE3_LATENCY2_FREQ) + if((HCLK_Frequency > UTILS_SCALE3_LATENCY2_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_2; + } + else + { + if((HCLK_Frequency > UTILS_SCALE3_LATENCY1_FREQ)&&(latency == LL_FLASH_LATENCY_0)) + { + latency = LL_FLASH_LATENCY_1; + } + } + } +#endif /*UTILS_SCALE1_LATENCY2_FREQ */ +#endif /* LL_PWR_REGU_VOLTAGE_SCALE3 */ + + LL_FLASH_SetLatency(latency); + /* Check that the new number of wait states is taken into account to access the Flash + memory by reading the FLASH_ACR register */ + timeout = 2; + do + { + /* Wait for Flash latency to be updated */ + getlatency = LL_FLASH_GetLatency(); + timeout--; + } while ((getlatency != latency) && (timeout > 0)); + + if(getlatency != latency) + { + status = ERROR; + } + else + { + status = SUCCESS; + } + } + return status; +} + +/** + * @brief This function configures system clock at maximum frequency with HSI as clock source of the PLL + * @note The application need to ensure that PLL is disabled. + * @note Function is based on the following formula: + * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLP) + * - PLLM: ensure that the VCO input frequency ranges from @ref RCC_PLLVCO_INPUT_MIN to @ref RCC_PLLVCO_INPUT_MAX (PLLVCO_input = HSI frequency / PLLM) + * - PLLN: ensure that the VCO output frequency is between @ref RCC_PLLVCO_OUTPUT_MIN and @ref RCC_PLLVCO_OUTPUT_MAX (PLLVCO_output = PLLVCO_input * PLLN) + * - PLLP: ensure that max frequency at 180000000 Hz is reach (PLLVCO_output / PLLP) + * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains + * the configuration information for the PLL. + * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains + * the configuration information for the BUS prescalers. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Max frequency configuration done + * - ERROR: Max frequency configuration not done + */ +ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, + LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) +{ + ErrorStatus status = SUCCESS; + uint32_t pllfreq = 0U; + + /* Check if one of the PLL is enabled */ + if(UTILS_PLL_IsBusy() == SUCCESS) + { + /* Calculate the new PLL output frequency */ + pllfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct); + + /* Enable HSI if not enabled */ + if(LL_RCC_HSI_IsReady() != 1U) + { + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1U) + { + /* Wait for HSI ready */ + } + } + + /* Configure PLL */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, + UTILS_PLLInitStruct->PLLP); + + /* Enable PLL and switch system clock to PLL */ + status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); + } + else + { + /* Current PLL configuration cannot be modified */ + status = ERROR; + } + + return status; +} + +/** + * @brief This function configures system clock with HSE as clock source of the PLL + * @note The application need to ensure that PLL is disabled. + * - PLL output frequency = (((HSI frequency / PLLM) * PLLN) / PLLP) + * - PLLM: ensure that the VCO input frequency ranges from @ref RCC_PLLVCO_INPUT_MIN to @ref RCC_PLLVCO_INPUT_MAX (PLLVCO_input = HSI frequency / PLLM) + * - PLLN: ensure that the VCO output frequency is between @ref RCC_PLLVCO_OUTPUT_MIN and @ref RCC_PLLVCO_OUTPUT_MAX (PLLVCO_output = PLLVCO_input * PLLN) + * - PLLP: ensure that max frequency at 180000000 Hz is reach (PLLVCO_output / PLLP) + * @param HSEFrequency Value between Min_Data = 4000000 and Max_Data = 26000000 + * @param HSEBypass This parameter can be one of the following values: + * @arg @ref LL_UTILS_HSEBYPASS_ON + * @arg @ref LL_UTILS_HSEBYPASS_OFF + * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains + * the configuration information for the PLL. + * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains + * the configuration information for the BUS prescalers. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: Max frequency configuration done + * - ERROR: Max frequency configuration not done + */ +ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass, + LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) +{ + ErrorStatus status = SUCCESS; + uint32_t pllfreq = 0U; + + /* Check the parameters */ + assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency)); + assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass)); + + /* Check if one of the PLL is enabled */ + if(UTILS_PLL_IsBusy() == SUCCESS) + { + /* Calculate the new PLL output frequency */ + pllfreq = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct); + + /* Enable HSE if not enabled */ + if(LL_RCC_HSE_IsReady() != 1U) + { + /* Check if need to enable HSE bypass feature or not */ + if(HSEBypass == LL_UTILS_HSEBYPASS_ON) + { + LL_RCC_HSE_EnableBypass(); + } + else + { + LL_RCC_HSE_DisableBypass(); + } + + /* Enable HSE */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1U) + { + /* Wait for HSE ready */ + } + } + + /* Configure PLL */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, UTILS_PLLInitStruct->PLLM, UTILS_PLLInitStruct->PLLN, + UTILS_PLLInitStruct->PLLP); + + /* Enable PLL and switch system clock to PLL */ + status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct); + } + else + { + /* Current PLL configuration cannot be modified */ + status = ERROR; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup UTILS_LL_Private_Functions + * @{ + */ +/** + * @brief Function to check that PLL can be modified + * @param PLL_InputFrequency PLL input frequency (in Hz) + * @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains + * the configuration information for the PLL. + * @retval PLL output frequency (in Hz) + */ +static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct) +{ + uint32_t pllfreq = 0U; + + /* Check the parameters */ + assert_param(IS_LL_UTILS_PLLM_VALUE(UTILS_PLLInitStruct->PLLM)); + assert_param(IS_LL_UTILS_PLLN_VALUE(UTILS_PLLInitStruct->PLLN)); + assert_param(IS_LL_UTILS_PLLP_VALUE(UTILS_PLLInitStruct->PLLP)); + + /* Check different PLL parameters according to RM */ + /* - PLLM: ensure that the VCO input frequency ranges from @ref UTILS_PLLVCO_INPUT_MIN to @ref UTILS_PLLVCO_INPUT_MAX MHz. */ + pllfreq = PLL_InputFrequency / (UTILS_PLLInitStruct->PLLM & (RCC_PLLCFGR_PLLM >> RCC_PLLCFGR_PLLM_Pos)); + assert_param(IS_LL_UTILS_PLLVCO_INPUT(pllfreq)); + + /* - PLLN: ensure that the VCO output frequency is between @ref UTILS_PLLVCO_OUTPUT_MIN and @ref UTILS_PLLVCO_OUTPUT_MAX .*/ + pllfreq = pllfreq * (UTILS_PLLInitStruct->PLLN & (RCC_PLLCFGR_PLLN >> RCC_PLLCFGR_PLLN_Pos)); + assert_param(IS_LL_UTILS_PLLVCO_OUTPUT(pllfreq)); + + /* - PLLP: ensure that max frequency at @ref RCC_MAX_FREQUENCY Hz is reached */ + pllfreq = pllfreq / (((UTILS_PLLInitStruct->PLLP >> RCC_PLLCFGR_PLLP_Pos) + 1) * 2); + assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq)); + + return pllfreq; +} + +/** + * @brief Function to check that PLL can be modified + * @retval An ErrorStatus enumeration value: + * - SUCCESS: PLL modification can be done + * - ERROR: PLL is busy + */ +static ErrorStatus UTILS_PLL_IsBusy(void) +{ + ErrorStatus status = SUCCESS; + + /* Check if PLL is busy*/ + if(LL_RCC_PLL_IsReady() != 0U) + { + /* PLL configuration cannot be modified */ + status = ERROR; + } + +#if defined(RCC_PLLSAI_SUPPORT) + /* Check if PLLSAI is busy*/ + if(LL_RCC_PLLSAI_IsReady() != 0U) + { + /* PLLSAI1 configuration cannot be modified */ + status = ERROR; + } +#endif /*RCC_PLLSAI_SUPPORT*/ +#if defined(RCC_PLLI2S_SUPPORT) + /* Check if PLLI2S is busy*/ + if(LL_RCC_PLLI2S_IsReady() != 0U) + { + /* PLLI2S configuration cannot be modified */ + status = ERROR; + } +#endif /*RCC_PLLI2S_SUPPORT*/ + return status; +} + +/** + * @brief Function to enable PLL and switch system clock to PLL + * @param SYSCLK_Frequency SYSCLK frequency + * @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains + * the configuration information for the BUS prescalers. + * @retval An ErrorStatus enumeration value: + * - SUCCESS: No problem to switch system to PLL + * - ERROR: Problem to switch system to PLL + */ +static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct) +{ + ErrorStatus status = SUCCESS; + uint32_t hclk_frequency = 0U; + + assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider)); + assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider)); + assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider)); + + /* Calculate HCLK frequency */ + hclk_frequency = __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider); + + /* Increasing the number of wait states because of higher CPU frequency */ + if(SystemCoreClock < hclk_frequency) + { + /* Set FLASH latency to highest latency */ + status = LL_SetFlashLatency(hclk_frequency); + } + + /* Update system clock configuration */ + if(status == SUCCESS) + { + /* Enable PLL */ + LL_RCC_PLL_Enable(); + while (LL_RCC_PLL_IsReady() != 1U) + { + /* Wait for PLL ready */ + } + + /* Sysclk activation on the main PLL */ + LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) + { + /* Wait for system clock switch to PLL */ + } + + /* Set APB1 & APB2 prescaler*/ + LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider); + LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider); + } + + /* Decreasing the number of wait states because of lower CPU frequency */ + if(SystemCoreClock > hclk_frequency) + { + /* Set FLASH latency to lowest latency */ + status = LL_SetFlashLatency(hclk_frequency); + } + + /* Update SystemCoreClock variable */ + if(status == SUCCESS) + { + LL_SetSystemCoreClock(hclk_frequency); + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ diff --git a/libs/STM32F4xx_HAL_Driver/_htmresc/mini-st.css b/libs/STM32F4xx_HAL_Driver/_htmresc/mini-st.css new file mode 100644 index 0000000..71fbc14 --- /dev/null +++ b/libs/STM32F4xx_HAL_Driver/_htmresc/mini-st.css @@ -0,0 +1,1700 @@ +@charset "UTF-8"; +/* + Flavor name: Default (mini-default) + Author: Angelos Chalaris (chalarangelo@gmail.com) + Maintainers: Angelos Chalaris + mini.css version: v3.0.0-alpha.3 +*/ +/* + Browsers resets and base typography. +*/ +/* Core module CSS variable definitions */ +:root { + --fore-color: #111; + --secondary-fore-color: #444; + --back-color: #f8f8f8; + --secondary-back-color: #f0f0f0; + --blockquote-color: #f57c00; + --pre-color: #1565c0; + --border-color: #aaa; + --secondary-border-color: #ddd; + --heading-ratio: 1.19; + --universal-margin: 0.5rem; + --universal-padding: 0.125rem; + --universal-border-radius: 0.125rem; + --a-link-color: #0277bd; + --a-visited-color: #01579b; } + +html { + font-size: 14px; } + +a, b, del, em, i, ins, q, span, strong, u { + font-size: 1em; } + +html, * { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", Helvetica, sans-serif; + line-height: 1.4; + -webkit-text-size-adjust: 100%; } + +* { + font-size: 1rem; } + +body { + margin: 0; + color: var(--fore-color); + background: var(--back-color); } + +details { + display: block; } + +summary { + display: list-item; } + +abbr[title] { + border-bottom: none; + text-decoration: underline dotted; } + +input { + overflow: visible; } + +img { + max-width: 100%; + height: auto; } + +h1, h2, h3, h4, h5, h6 { + line-height: 1.2; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + font-weight: 500; } + h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { + color: var(--secondary-fore-color); + display: block; + margin-top: -0.25rem; } + +h1 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio) * var(--heading-ratio)); } + +h2 { + font-size: calc(1rem * var(--heading-ratio) * var(--heading-ratio); ); + background: var(--mark-back-color); + font-weight: 600; + padding: 0.1em 0.5em 0.2em 0.5em; + color: var(--mark-fore-color); } + +h3 { + font-size: calc(1rem * var(--heading-ratio)); + padding-left: calc(2 * var(--universal-margin)); + /* background: var(--border-color); */ + } + +h4 { + font-size: 1rem;); + padding-left: calc(4 * var(--universal-margin)); } + +h5 { + font-size: 1rem; } + +h6 { + font-size: calc(1rem / var(--heading-ratio)); } + +p { + margin: var(--universal-margin); } + +ol, ul { + margin: var(--universal-margin); + padding-left: calc(6 * var(--universal-margin)); } + +b, strong { + font-weight: 700; } + +hr { + box-sizing: content-box; + border: 0; + line-height: 1.25em; + margin: var(--universal-margin); + height: 0.0625rem; + background: linear-gradient(to right, transparent, var(--border-color) 20%, var(--border-color) 80%, transparent); } + +blockquote { + display: block; + position: relative; + font-style: italic; + color: var(--secondary-fore-color); + margin: var(--universal-margin); + padding: calc(3 * var(--universal-padding)); + border: 0.0625rem solid var(--secondary-border-color); + border-left: 0.375rem solid var(--blockquote-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + blockquote:before { + position: absolute; + top: calc(0rem - var(--universal-padding)); + left: 0; + font-family: sans-serif; + font-size: 3rem; + font-weight: 700; + content: "\201c"; + color: var(--blockquote-color); } + blockquote[cite]:after { + font-style: normal; + font-size: 0.75em; + font-weight: 700; + content: "\a— " attr(cite); + white-space: pre; } + +code, kbd, pre, samp { + font-family: Menlo, Consolas, monospace; + font-size: 0.85em; } + +code { + background: var(--secondary-back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +kbd { + background: var(--fore-color); + color: var(--back-color); + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + +pre { + overflow: auto; + background: var(--secondary-back-color); + padding: calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + border: 0.0625rem solid var(--secondary-border-color); + border-left: 0.25rem solid var(--pre-color); + border-radius: 0 var(--universal-border-radius) var(--universal-border-radius) 0; } + +sup, sub, code, kbd { + line-height: 0; + position: relative; + vertical-align: baseline; } + +small, sup, sub, figcaption { + font-size: 0.75em; } + +sup { + top: -0.5em; } + +sub { + bottom: -0.25em; } + +figure { + margin: var(--universal-margin); } + +figcaption { + color: var(--secondary-fore-color); } + +a { + text-decoration: none; } + a:link { + color: var(--a-link-color); } + a:visited { + color: var(--a-visited-color); } + a:hover, a:focus { + text-decoration: underline; } + +/* + Definitions for the grid system, cards and containers. +*/ +.container { + margin: 0 auto; + padding: 0 calc(1.5 * var(--universal-padding)); } + +.row { + box-sizing: border-box; + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; } + +.col-sm, +[class^='col-sm-'], +[class^='col-sm-offset-'], +.row[class*='cols-sm-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + +.col-sm, +.row.cols-sm > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + +.col-sm-1, +.row.cols-sm-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + +.col-sm-offset-0 { + margin-left: 0; } + +.col-sm-2, +.row.cols-sm-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + +.col-sm-offset-1 { + margin-left: 8.3333333333%; } + +.col-sm-3, +.row.cols-sm-3 > * { + max-width: 25%; + flex-basis: 25%; } + +.col-sm-offset-2 { + margin-left: 16.6666666667%; } + +.col-sm-4, +.row.cols-sm-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + +.col-sm-offset-3 { + margin-left: 25%; } + +.col-sm-5, +.row.cols-sm-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + +.col-sm-offset-4 { + margin-left: 33.3333333333%; } + +.col-sm-6, +.row.cols-sm-6 > * { + max-width: 50%; + flex-basis: 50%; } + +.col-sm-offset-5 { + margin-left: 41.6666666667%; } + +.col-sm-7, +.row.cols-sm-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + +.col-sm-offset-6 { + margin-left: 50%; } + +.col-sm-8, +.row.cols-sm-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + +.col-sm-offset-7 { + margin-left: 58.3333333333%; } + +.col-sm-9, +.row.cols-sm-9 > * { + max-width: 75%; + flex-basis: 75%; } + +.col-sm-offset-8 { + margin-left: 66.6666666667%; } + +.col-sm-10, +.row.cols-sm-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + +.col-sm-offset-9 { + margin-left: 75%; } + +.col-sm-11, +.row.cols-sm-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + +.col-sm-offset-10 { + margin-left: 83.3333333333%; } + +.col-sm-12, +.row.cols-sm-12 > * { + max-width: 100%; + flex-basis: 100%; } + +.col-sm-offset-11 { + margin-left: 91.6666666667%; } + +.col-sm-normal { + order: initial; } + +.col-sm-first { + order: -999; } + +.col-sm-last { + order: 999; } + +@media screen and (min-width: 500px) { + .col-md, + [class^='col-md-'], + [class^='col-md-offset-'], + .row[class*='cols-md-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-md, + .row.cols-md > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-md-1, + .row.cols-md-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-md-offset-0 { + margin-left: 0; } + + .col-md-2, + .row.cols-md-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-md-offset-1 { + margin-left: 8.3333333333%; } + + .col-md-3, + .row.cols-md-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-md-offset-2 { + margin-left: 16.6666666667%; } + + .col-md-4, + .row.cols-md-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-md-offset-3 { + margin-left: 25%; } + + .col-md-5, + .row.cols-md-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-md-offset-4 { + margin-left: 33.3333333333%; } + + .col-md-6, + .row.cols-md-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-md-offset-5 { + margin-left: 41.6666666667%; } + + .col-md-7, + .row.cols-md-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-md-offset-6 { + margin-left: 50%; } + + .col-md-8, + .row.cols-md-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-md-offset-7 { + margin-left: 58.3333333333%; } + + .col-md-9, + .row.cols-md-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-md-offset-8 { + margin-left: 66.6666666667%; } + + .col-md-10, + .row.cols-md-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-md-offset-9 { + margin-left: 75%; } + + .col-md-11, + .row.cols-md-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-md-offset-10 { + margin-left: 83.3333333333%; } + + .col-md-12, + .row.cols-md-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-md-offset-11 { + margin-left: 91.6666666667%; } + + .col-md-normal { + order: initial; } + + .col-md-first { + order: -999; } + + .col-md-last { + order: 999; } } +@media screen and (min-width: 1280px) { + .col-lg, + [class^='col-lg-'], + [class^='col-lg-offset-'], + .row[class*='cols-lg-'] > * { + box-sizing: border-box; + flex: 0 0 auto; + padding: 0 calc(var(--universal-padding) / 2); } + + .col-lg, + .row.cols-lg > * { + max-width: 100%; + flex-grow: 1; + flex-basis: 0; } + + .col-lg-1, + .row.cols-lg-1 > * { + max-width: 8.3333333333%; + flex-basis: 8.3333333333%; } + + .col-lg-offset-0 { + margin-left: 0; } + + .col-lg-2, + .row.cols-lg-2 > * { + max-width: 16.6666666667%; + flex-basis: 16.6666666667%; } + + .col-lg-offset-1 { + margin-left: 8.3333333333%; } + + .col-lg-3, + .row.cols-lg-3 > * { + max-width: 25%; + flex-basis: 25%; } + + .col-lg-offset-2 { + margin-left: 16.6666666667%; } + + .col-lg-4, + .row.cols-lg-4 > * { + max-width: 33.3333333333%; + flex-basis: 33.3333333333%; } + + .col-lg-offset-3 { + margin-left: 25%; } + + .col-lg-5, + .row.cols-lg-5 > * { + max-width: 41.6666666667%; + flex-basis: 41.6666666667%; } + + .col-lg-offset-4 { + margin-left: 33.3333333333%; } + + .col-lg-6, + .row.cols-lg-6 > * { + max-width: 50%; + flex-basis: 50%; } + + .col-lg-offset-5 { + margin-left: 41.6666666667%; } + + .col-lg-7, + .row.cols-lg-7 > * { + max-width: 58.3333333333%; + flex-basis: 58.3333333333%; } + + .col-lg-offset-6 { + margin-left: 50%; } + + .col-lg-8, + .row.cols-lg-8 > * { + max-width: 66.6666666667%; + flex-basis: 66.6666666667%; } + + .col-lg-offset-7 { + margin-left: 58.3333333333%; } + + .col-lg-9, + .row.cols-lg-9 > * { + max-width: 75%; + flex-basis: 75%; } + + .col-lg-offset-8 { + margin-left: 66.6666666667%; } + + .col-lg-10, + .row.cols-lg-10 > * { + max-width: 83.3333333333%; + flex-basis: 83.3333333333%; } + + .col-lg-offset-9 { + margin-left: 75%; } + + .col-lg-11, + .row.cols-lg-11 > * { + max-width: 91.6666666667%; + flex-basis: 91.6666666667%; } + + .col-lg-offset-10 { + margin-left: 83.3333333333%; } + + .col-lg-12, + .row.cols-lg-12 > * { + max-width: 100%; + flex-basis: 100%; } + + .col-lg-offset-11 { + margin-left: 91.6666666667%; } + + .col-lg-normal { + order: initial; } + + .col-lg-first { + order: -999; } + + .col-lg-last { + order: 999; } } +/* Card component CSS variable definitions */ +:root { + --card-back-color: #f8f8f8; + --card-fore-color: #111; + --card-border-color: #ddd; } + +.card { + display: flex; + flex-direction: column; + justify-content: space-between; + align-self: center; + position: relative; + width: 100%; + background: var(--card-back-color); + color: var(--card-fore-color); + border: 0.0625rem solid var(--card-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + overflow: hidden; } + @media screen and (min-width: 320px) { + .card { + max-width: 320px; } } + .card > .sectione { + background: var(--card-back-color); + color: var(--card-fore-color); + box-sizing: border-box; + margin: 0; + border: 0; + border-radius: 0; + border-bottom: 0.0625rem solid var(--card-border-color); + padding: var(--universal-padding); + width: 100%; } + .card > .sectione.media { + height: 200px; + padding: 0; + -o-object-fit: cover; + object-fit: cover; } + .card > .sectione:last-child { + border-bottom: 0; } + +/* + Custom elements for card elements. +*/ +@media screen and (min-width: 240px) { + .card.small { + max-width: 240px; } } +@media screen and (min-width: 480px) { + .card.large { + max-width: 480px; } } +.card.fluid { + max-width: 100%; + width: auto; } + +.card.warning { +/* --card-back-color: #ffca28; */ + --card-back-color: #e5b8b7; + --card-border-color: #e8b825; } + +.card.error { + --card-back-color: #b71c1c; + --card-fore-color: #f8f8f8; + --card-border-color: #a71a1a; } + +.card > .sectione.dark { + --card-back-color: #e0e0e0; } + +.card > .sectione.double-padded { + padding: calc(1.5 * var(--universal-padding)); } + +/* + Definitions for forms and input elements. +*/ +/* Input_control module CSS variable definitions */ +:root { + --form-back-color: #f0f0f0; + --form-fore-color: #111; + --form-border-color: #ddd; + --input-back-color: #f8f8f8; + --input-fore-color: #111; + --input-border-color: #ddd; + --input-focus-color: #0288d1; + --input-invalid-color: #d32f2f; + --button-back-color: #e2e2e2; + --button-hover-back-color: #dcdcdc; + --button-fore-color: #212121; + --button-border-color: transparent; + --button-hover-border-color: transparent; + --button-group-border-color: rgba(124, 124, 124, 0.54); } + +form { + background: var(--form-back-color); + color: var(--form-fore-color); + border: 0.0625rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); } + +fieldset { + border: 0.0625rem solid var(--form-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 4); + padding: var(--universal-padding); } + +legend { + box-sizing: border-box; + display: table; + max-width: 100%; + white-space: normal; + font-weight: 700; + padding: calc(var(--universal-padding) / 2); } + +label { + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +.input-group { + display: inline-block; } + .input-group.fluid { + display: flex; + align-items: center; + justify-content: center; } + .input-group.fluid > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + @media screen and (max-width: 499px) { + .input-group.fluid { + align-items: stretch; + flex-direction: column; } } + .input-group.vertical { + display: flex; + align-items: stretch; + flex-direction: column; } + .input-group.vertical > input { + max-width: 100%; + flex-grow: 1; + flex-basis: 0px; } + +[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { + height: auto; } + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; } + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +input:not([type]), [type="text"], [type="email"], [type="number"], [type="search"], +[type="password"], [type="url"], [type="tel"], [type="checkbox"], [type="radio"], textarea, select { + box-sizing: border-box; + background: var(--input-back-color); + color: var(--input-fore-color); + border: 0.0625rem solid var(--input-border-color); + border-radius: var(--universal-border-radius); + margin: calc(var(--universal-margin) / 2); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + +input:not([type="button"]):not([type="submit"]):not([type="reset"]):hover, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus, textarea:hover, textarea:focus, select:hover, select:focus { + border-color: var(--input-focus-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"]):invalid, input:not([type="button"]):not([type="submit"]):not([type="reset"]):focus:invalid, textarea:invalid, textarea:focus:invalid, select:invalid, select:focus:invalid { + border-color: var(--input-invalid-color); + box-shadow: none; } +input:not([type="button"]):not([type="submit"]):not([type="reset"])[readonly], textarea[readonly], select[readonly] { + background: var(--secondary-back-color); } + +select { + max-width: 100%; } + +option { + overflow: hidden; + text-overflow: ellipsis; } + +[type="checkbox"], [type="radio"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + height: calc(1rem + var(--universal-padding) / 2); + width: calc(1rem + var(--universal-padding) / 2); + vertical-align: text-bottom; + padding: 0; + flex-basis: calc(1rem + var(--universal-padding) / 2) !important; + flex-grow: 0 !important; } + [type="checkbox"]:checked:before, [type="radio"]:checked:before { + position: absolute; } + +[type="checkbox"]:checked:before { + content: '\2713'; + font-family: sans-serif; + font-size: calc(1rem + var(--universal-padding) / 2); + top: calc(0rem - var(--universal-padding)); + left: calc(var(--universal-padding) / 4); } + +[type="radio"] { + border-radius: 100%; } + [type="radio"]:checked:before { + border-radius: 100%; + content: ''; + top: calc(0.0625rem + var(--universal-padding) / 2); + left: calc(0.0625rem + var(--universal-padding) / 2); + background: var(--input-fore-color); + width: 0.5rem; + height: 0.5rem; } + +:placeholder-shown { + color: var(--input-fore-color); } + +::-ms-placeholder { + color: var(--input-fore-color); + opacity: 0.54; } + +button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +button, html [type="button"], [type="reset"], [type="submit"] { + -webkit-appearance: button; } + +button { + overflow: visible; + text-transform: none; } + +button, [type="button"], [type="submit"], [type="reset"], +a.button, label.button, .button, +a[role="button"], label[role="button"], [role="button"] { + display: inline-block; + background: var(--button-back-color); + color: var(--button-fore-color); + border: 0.0625rem solid var(--button-border-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); + margin: var(--universal-margin); + text-decoration: none; + cursor: pointer; + transition: background 0.3s; } + button:hover, button:focus, [type="button"]:hover, [type="button"]:focus, [type="submit"]:hover, [type="submit"]:focus, [type="reset"]:hover, [type="reset"]:focus, + a.button:hover, + a.button:focus, label.button:hover, label.button:focus, .button:hover, .button:focus, + a[role="button"]:hover, + a[role="button"]:focus, label[role="button"]:hover, label[role="button"]:focus, [role="button"]:hover, [role="button"]:focus { + background: var(--button-hover-back-color); + border-color: var(--button-hover-border-color); } + +input:disabled, input[disabled], textarea:disabled, textarea[disabled], select:disabled, select[disabled], button:disabled, button[disabled], .button:disabled, .button[disabled], [role="button"]:disabled, [role="button"][disabled] { + cursor: not-allowed; + opacity: 0.75; } + +.button-group { + display: flex; + border: 0.0625rem solid var(--button-group-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + .button-group > button, .button-group [type="button"], .button-group > [type="submit"], .button-group > [type="reset"], .button-group > .button, .button-group > [role="button"] { + margin: 0; + max-width: 100%; + flex: 1 1 auto; + text-align: center; + border: 0; + border-radius: 0; + box-shadow: none; } + .button-group > :not(:first-child) { + border-left: 0.0625rem solid var(--button-group-border-color); } + @media screen and (max-width: 499px) { + .button-group { + flex-direction: column; } + .button-group > :not(:first-child) { + border: 0; + border-top: 0.0625rem solid var(--button-group-border-color); } } + +/* + Custom elements for forms and input elements. +*/ +button.primary, [type="button"].primary, [type="submit"].primary, [type="reset"].primary, .button.primary, [role="button"].primary { + --button-back-color: #1976d2; + --button-fore-color: #f8f8f8; } + button.primary:hover, button.primary:focus, [type="button"].primary:hover, [type="button"].primary:focus, [type="submit"].primary:hover, [type="submit"].primary:focus, [type="reset"].primary:hover, [type="reset"].primary:focus, .button.primary:hover, .button.primary:focus, [role="button"].primary:hover, [role="button"].primary:focus { + --button-hover-back-color: #1565c0; } + +button.secondary, [type="button"].secondary, [type="submit"].secondary, [type="reset"].secondary, .button.secondary, [role="button"].secondary { + --button-back-color: #d32f2f; + --button-fore-color: #f8f8f8; } + button.secondary:hover, button.secondary:focus, [type="button"].secondary:hover, [type="button"].secondary:focus, [type="submit"].secondary:hover, [type="submit"].secondary:focus, [type="reset"].secondary:hover, [type="reset"].secondary:focus, .button.secondary:hover, .button.secondary:focus, [role="button"].secondary:hover, [role="button"].secondary:focus { + --button-hover-back-color: #c62828; } + +button.tertiary, [type="button"].tertiary, [type="submit"].tertiary, [type="reset"].tertiary, .button.tertiary, [role="button"].tertiary { + --button-back-color: #308732; + --button-fore-color: #f8f8f8; } + button.tertiary:hover, button.tertiary:focus, [type="button"].tertiary:hover, [type="button"].tertiary:focus, [type="submit"].tertiary:hover, [type="submit"].tertiary:focus, [type="reset"].tertiary:hover, [type="reset"].tertiary:focus, .button.tertiary:hover, .button.tertiary:focus, [role="button"].tertiary:hover, [role="button"].tertiary:focus { + --button-hover-back-color: #277529; } + +button.inverse, [type="button"].inverse, [type="submit"].inverse, [type="reset"].inverse, .button.inverse, [role="button"].inverse { + --button-back-color: #212121; + --button-fore-color: #f8f8f8; } + button.inverse:hover, button.inverse:focus, [type="button"].inverse:hover, [type="button"].inverse:focus, [type="submit"].inverse:hover, [type="submit"].inverse:focus, [type="reset"].inverse:hover, [type="reset"].inverse:focus, .button.inverse:hover, .button.inverse:focus, [role="button"].inverse:hover, [role="button"].inverse:focus { + --button-hover-back-color: #111; } + +button.small, [type="button"].small, [type="submit"].small, [type="reset"].small, .button.small, [role="button"].small { + padding: calc(0.5 * var(--universal-padding)) calc(0.75 * var(--universal-padding)); + margin: var(--universal-margin); } + +button.large, [type="button"].large, [type="submit"].large, [type="reset"].large, .button.large, [role="button"].large { + padding: calc(1.5 * var(--universal-padding)) calc(2 * var(--universal-padding)); + margin: var(--universal-margin); } + +/* + Definitions for navigation elements. +*/ +/* Navigation module CSS variable definitions */ +:root { + --header-back-color: #f8f8f8; + --header-hover-back-color: #f0f0f0; + --header-fore-color: #444; + --header-border-color: #ddd; + --nav-back-color: #f8f8f8; + --nav-hover-back-color: #f0f0f0; + --nav-fore-color: #444; + --nav-border-color: #ddd; + --nav-link-color: #0277bd; + --footer-fore-color: #444; + --footer-back-color: #f8f8f8; + --footer-border-color: #ddd; + --footer-link-color: #0277bd; + --drawer-back-color: #f8f8f8; + --drawer-hover-back-color: #f0f0f0; + --drawer-border-color: #ddd; + --drawer-close-color: #444; } + +header { + height: 3.1875rem; + background: var(--header-back-color); + color: var(--header-fore-color); + border-bottom: 0.0625rem solid var(--header-border-color); + padding: calc(var(--universal-padding) / 4) 0; + white-space: nowrap; + overflow-x: auto; + overflow-y: hidden; } + header.row { + box-sizing: content-box; } + header .logo { + color: var(--header-fore-color); + font-size: 1.75rem; + padding: var(--universal-padding) calc(2 * var(--universal-padding)); + text-decoration: none; } + header button, header [type="button"], header .button, header [role="button"] { + box-sizing: border-box; + position: relative; + top: calc(0rem - var(--universal-padding) / 4); + height: calc(3.1875rem + var(--universal-padding) / 2); + background: var(--header-back-color); + line-height: calc(3.1875rem - var(--universal-padding) * 1.5); + text-align: center; + color: var(--header-fore-color); + border: 0; + border-radius: 0; + margin: 0; + text-transform: uppercase; } + header button:hover, header button:focus, header [type="button"]:hover, header [type="button"]:focus, header .button:hover, header .button:focus, header [role="button"]:hover, header [role="button"]:focus { + background: var(--header-hover-back-color); } + +nav { + background: var(--nav-back-color); + color: var(--nav-fore-color); + border: 0.0625rem solid var(--nav-border-color); + border-radius: var(--universal-border-radius); + margin: var(--universal-margin); } + nav * { + padding: var(--universal-padding) calc(1.5 * var(--universal-padding)); } + nav a, nav a:visited { + display: block; + color: var(--nav-link-color); + border-radius: var(--universal-border-radius); + transition: background 0.3s; } + nav a:hover, nav a:focus, nav a:visited:hover, nav a:visited:focus { + text-decoration: none; + background: var(--nav-hover-back-color); } + nav .sublink-1 { + position: relative; + margin-left: calc(2 * var(--universal-padding)); } + nav .sublink-1:before { + position: absolute; + left: calc(var(--universal-padding) - 1 * var(--universal-padding)); + top: -0.0625rem; + content: ''; + height: 100%; + border: 0.0625rem solid var(--nav-border-color); + border-left: 0; } + nav .sublink-2 { + position: relative; + margin-left: calc(4 * var(--universal-padding)); } + nav .sublink-2:before { + position: absolute; + left: calc(var(--universal-padding) - 3 * var(--universal-padding)); + top: -0.0625rem; + content: ''; + height: 100%; + border: 0.0625rem solid var(--nav-border-color); + border-left: 0; } + +footer { + background: var(--footer-back-color); + color: var(--footer-fore-color); + border-top: 0.0625rem solid var(--footer-border-color); + padding: calc(2 * var(--universal-padding)) var(--universal-padding); + font-size: 0.875rem; } + footer a, footer a:visited { + color: var(--footer-link-color); } + +header.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + top: 0; } + +footer.sticky { + position: -webkit-sticky; + position: sticky; + z-index: 1101; + bottom: 0; } + +.drawer-toggle:before { + display: inline-block; + position: relative; + vertical-align: bottom; + content: '\00a0\2261\00a0'; + font-family: sans-serif; + font-size: 1.5em; } +@media screen and (min-width: 500px) { + .drawer-toggle:not(.persistent) { + display: none; } } + +[type="checkbox"].drawer { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].drawer + * { + display: block; + box-sizing: border-box; + position: fixed; + top: 0; + width: 320px; + height: 100vh; + overflow-y: auto; + background: var(--drawer-back-color); + border: 0.0625rem solid var(--drawer-border-color); + border-radius: 0; + margin: 0; + z-index: 1110; + right: -320px; + transition: right 0.3s; } + [type="checkbox"].drawer + * .drawer-close { + position: absolute; + top: var(--universal-margin); + right: var(--universal-margin); + z-index: 1111; + width: 2rem; + height: 2rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].drawer + * .drawer-close:before { + display: block; + content: '\00D7'; + color: var(--drawer-close-color); + position: relative; + font-family: sans-serif; + font-size: 2rem; + line-height: 1; + text-align: center; } + [type="checkbox"].drawer + * .drawer-close:hover, [type="checkbox"].drawer + * .drawer-close:focus { + background: var(--drawer-hover-back-color); } + @media screen and (max-width: 320px) { + [type="checkbox"].drawer + * { + width: 100%; } } + [type="checkbox"].drawer:checked + * { + right: 0; } + @media screen and (min-width: 500px) { + [type="checkbox"].drawer:not(.persistent) + * { + position: static; + height: 100%; + z-index: 1100; } + [type="checkbox"].drawer:not(.persistent) + * .drawer-close { + display: none; } } + +/* + Definitions for the responsive table component. +*/ +/* Table module CSS variable definitions. */ +:root { + --table-border-color: #aaa; + --table-border-separator-color: #666; + --table-head-back-color: #e6e6e6; + --table-head-fore-color: #111; + --table-body-back-color: #f8f8f8; + --table-body-fore-color: #111; + --table-body-alt-back-color: #eee; } + +table { + border-collapse: separate; + border-spacing: 0; + : margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); + display: flex; + flex: 0 1 auto; + flex-flow: row wrap; + padding: var(--universal-padding); + padding-top: 0; + margin: calc(1.5 * var(--universal-margin)) var(--universal-margin); } + table caption { + font-size: 1.25 * rem; + margin: calc(2 * var(--universal-margin)) 0; + max-width: 100%; + flex: 0 0 100%; + text-align: left;} + table thead, table tbody { + display: flex; + flex-flow: row wrap; + border: 0.0625rem solid var(--table-border-color); } + table thead { + z-index: 999; + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; + border-bottom: 0.0625rem solid var(--table-border-separator-color); } + table tbody { + border-top: 0; + margin-top: calc(0 - var(--universal-margin)); + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + table tr { + display: flex; + padding: 0; } + table th, table td { + padding: calc(0.5 * var(--universal-padding)); + font-size: 0.9rem; } + table th { + text-align: left; + background: var(--table-head-back-color); + color: var(--table-head-fore-color); } + table td { + background: var(--table-body-back-color); + color: var(--table-body-fore-color); + border-top: 0.0625rem solid var(--table-border-color); } + +table:not(.horizontal) { + overflow: auto; + max-height: 850px; } + table:not(.horizontal) thead, table:not(.horizontal) tbody { + max-width: 100%; + flex: 0 0 100%; } + table:not(.horizontal) tr { + flex-flow: row wrap; + flex: 0 0 100%; } + table:not(.horizontal) th, table:not(.horizontal) td { + flex: 1 0 0%; + overflow: hidden; + text-overflow: ellipsis; } + table:not(.horizontal) thead { + position: sticky; + top: 0; } + table:not(.horizontal) tbody tr:first-child td { + border-top: 0; } + +table.horizontal { + border: 0; } + table.horizontal thead, table.horizontal tbody { + border: 0; + flex-flow: row nowrap; } + table.horizontal tbody { + overflow: auto; + justify-content: space-between; + flex: 1 0 0; + margin-left: calc( 4 * var(--universal-margin)); + padding-bottom: calc(var(--universal-padding) / 4); } + table.horizontal tr { + flex-direction: column; + flex: 1 0 auto; } + table.horizontal th, table.horizontal td { + width: 100%; + border: 0; + border-bottom: 0.0625rem solid var(--table-border-color); } + table.horizontal th:not(:first-child), table.horizontal td:not(:first-child) { + border-top: 0; } + table.horizontal th { + text-align: right; + border-left: 0.0625rem solid var(--table-border-color); + border-right: 0.0625rem solid var(--table-border-separator-color); } + table.horizontal thead tr:first-child { + padding-left: 0; } + table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0.0625rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td { + border-right: 0.0625rem solid var(--table-border-color); } + table.horizontal tbody tr:last-child td:first-child { + border-top-right-radius: 0.25rem; } + table.horizontal tbody tr:last-child td:last-child { + border-bottom-right-radius: 0.25rem; } + table.horizontal thead tr:first-child th:first-child { + border-top-left-radius: 0.25rem; } + table.horizontal thead tr:first-child th:last-child { + border-bottom-left-radius: 0.25rem; } + +@media screen and (max-width: 499px) { + table, table.horizontal { + border-collapse: collapse; + border: 0; + width: 100%; + display: table; } + table thead, table th, table.horizontal thead, table.horizontal th { + border: 0; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + table tbody, table.horizontal tbody { + border: 0; + display: table-row-group; } + table tr, table.horizontal tr { + display: block; + border: 0.0625rem solid var(--table-border-color); + border-radius: var(--universal-border-radius); + background: #fafafa; + padding: var(--universal-padding); + margin: var(--universal-margin); + margin-bottom: calc(2 * var(--universal-margin)); } + table th, table td, table.horizontal th, table.horizontal td { + width: auto; } + table td, table.horizontal td { + display: block; + border: 0; + text-align: right; } + table td:before, table.horizontal td:before { + content: attr(data-label); + float: left; + font-weight: 600; } + table th:first-child, table td:first-child, table.horizontal th:first-child, table.horizontal td:first-child { + border-top: 0; } + table tbody tr:last-child td, table.horizontal tbody tr:last-child td { + border-right: 0; } } +:root { + --table-body-alt-back-color: #eee; } + +table tr:nth-of-type(2n) > td { + background: var(--table-body-alt-back-color); } + +@media screen and (max-width: 500px) { + table tr:nth-of-type(2n) { + background: var(--table-body-alt-back-color); } } +:root { + --table-body-hover-back-color: #90caf9; } + +table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } + +@media screen and (max-width: 500px) { + table.hoverable tr:hover, table.hoverable tr:hover > td, table.hoverable tr:focus, table.hoverable tr:focus > td { + background: var(--table-body-hover-back-color); } } +/* + Definitions for contextual background elements, toasts and tooltips. +*/ +/* Contextual module CSS variable definitions */ +:root { + --mark-back-color: #0277bd; + --mark-fore-color: #fafafa; } + +mark { + background: var(--mark-back-color); + color: var(--mark-fore-color); + font-size: 0.95em; + line-height: 1em; + border-radius: var(--universal-border-radius); + padding: calc(var(--universal-padding) / 4) calc(var(--universal-padding) / 2); } + mark.inline-block { + display: inline-block; + font-size: 1em; + line-height: 1.5; + padding: calc(var(--universal-padding) / 2) var(--universal-padding); } + +:root { + --toast-back-color: #424242; + --toast-fore-color: #fafafa; } + +.toast { + position: fixed; + bottom: calc(var(--universal-margin) * 3); + left: 50%; + transform: translate(-50%, -50%); + z-index: 1111; + color: var(--toast-fore-color); + background: var(--toast-back-color); + border-radius: calc(var(--universal-border-radius) * 16); + padding: var(--universal-padding) calc(var(--universal-padding) * 3); } + +:root { + --tooltip-back-color: #212121; + --tooltip-fore-color: #fafafa; } + +.tooltip { + position: relative; + display: inline-block; } + .tooltip:before, .tooltip:after { + position: absolute; + opacity: 0; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: all 0.3s; + z-index: 1010; + left: 50%; } + .tooltip:not(.bottom):before, .tooltip:not(.bottom):after { + bottom: 75%; } + .tooltip.bottom:before, .tooltip.bottom:after { + top: 75%; } + .tooltip:hover:before, .tooltip:hover:after, .tooltip:focus:before, .tooltip:focus:after { + opacity: 1; + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); } + .tooltip:before { + content: ''; + background: transparent; + border: var(--universal-margin) solid transparent; + left: calc(50% - var(--universal-margin)); } + .tooltip:not(.bottom):before { + border-top-color: #212121; } + .tooltip.bottom:before { + border-bottom-color: #212121; } + .tooltip:after { + content: attr(aria-label); + color: var(--tooltip-fore-color); + background: var(--tooltip-back-color); + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + white-space: nowrap; + transform: translateX(-50%); } + .tooltip:not(.bottom):after { + margin-bottom: calc(2 * var(--universal-margin)); } + .tooltip.bottom:after { + margin-top: calc(2 * var(--universal-margin)); } + +:root { + --modal-overlay-color: rgba(0, 0, 0, 0.45); + --modal-close-color: #444; + --modal-close-hover-color: #f0f0f0; } + +[type="checkbox"].modal { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + [type="checkbox"].modal + div { + position: fixed; + top: 0; + left: 0; + display: none; + width: 100vw; + height: 100vh; + background: var(--modal-overlay-color); } + [type="checkbox"].modal + div .card { + margin: 0 auto; + max-height: 50vh; + overflow: auto; } + [type="checkbox"].modal + div .card .modal-close { + position: absolute; + top: 0; + right: 0; + width: 1.75rem; + height: 1.75rem; + border-radius: var(--universal-border-radius); + padding: var(--universal-padding); + margin: 0; + cursor: pointer; + transition: background 0.3s; } + [type="checkbox"].modal + div .card .modal-close:before { + display: block; + content: '\00D7'; + color: var(--modal-close-color); + position: relative; + font-family: sans-serif; + font-size: 1.75rem; + line-height: 1; + text-align: center; } + [type="checkbox"].modal + div .card .modal-close:hover, [type="checkbox"].modal + div .card .modal-close:focus { + background: var(--modal-close-hover-color); } + [type="checkbox"].modal:checked + div { + display: flex; + flex: 0 1 auto; + z-index: 1200; } + [type="checkbox"].modal:checked + div .card .modal-close { + z-index: 1211; } + +:root { + --collapse-label-back-color: #e8e8e8; + --collapse-label-fore-color: #212121; + --collapse-label-hover-back-color: #f0f0f0; + --collapse-selected-label-back-color: #ececec; + --collapse-border-color: #ddd; + --collapse-content-back-color: #fafafa; + --collapse-selected-label-border-color: #0277bd; } + +.collapse { + width: calc(100% - 2 * var(--universal-margin)); + opacity: 1; + display: flex; + flex-direction: column; + margin: var(--universal-margin); + border-radius: var(--universal-border-radius); } + .collapse > [type="radio"], .collapse > [type="checkbox"] { + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); } + .collapse > label { + flex-grow: 1; + display: inline-block; + height: 1.5rem; + cursor: pointer; + transition: background 0.3s; + color: var(--collapse-label-fore-color); + background: var(--collapse-label-back-color); + border: 0.0625rem solid var(--collapse-border-color); + padding: calc(1.5 * var(--universal-padding)); } + .collapse > label:hover, .collapse > label:focus { + background: var(--collapse-label-hover-back-color); } + .collapse > label + div { + flex-basis: auto; + height: 1px; + width: 1px; + margin: -1px; + overflow: hidden; + position: absolute; + clip: rect(0 0 0 0); + -webkit-clip-path: inset(100%); + clip-path: inset(100%); + transition: max-height 0.3s; + max-height: 1px; } + .collapse > :checked + label { + background: var(--collapse-selected-label-back-color); + border-bottom-color: var(--collapse-selected-label-border-color); } + .collapse > :checked + label + div { + box-sizing: border-box; + position: relative; + width: 100%; + height: auto; + overflow: auto; + margin: 0; + background: var(--collapse-content-back-color); + border: 0.0625rem solid var(--collapse-border-color); + border-top: 0; + padding: var(--universal-padding); + clip: auto; + -webkit-clip-path: inset(0%); + clip-path: inset(0%); + max-height: 850px; } + .collapse > label:not(:first-of-type) { + border-top: 0; } + .collapse > label:first-of-type { + border-radius: var(--universal-border-radius) var(--universal-border-radius) 0 0; } + .collapse > label:last-of-type:not(:first-of-type) { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + .collapse > label:last-of-type:first-of-type { + border-radius: var(--universal-border-radius); } + .collapse > :checked:last-of-type:not(:first-of-type) + label { + border-radius: 0; } + .collapse > :checked:last-of-type + label + div { + border-radius: 0 0 var(--universal-border-radius) var(--universal-border-radius); } + +/* + Custom elements for contextual background elements, toasts and tooltips. +*/ +mark.secondary { + --mark-back-color: #d32f2f; } + +mark.tertiary { + --mark-back-color: #308732; } + +mark.tag { + padding: calc(var(--universal-padding)/2) var(--universal-padding); + border-radius: 1em; } + +/* + Definitions for progress elements and spinners. +*/ +/* Progess module CSS variable definitions */ +:root { + --progress-back-color: #ddd; + --progress-fore-color: #555; } + +progress { + display: block; + vertical-align: baseline; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + height: 0.75rem; + width: calc(100% - 2 * var(--universal-margin)); + margin: var(--universal-margin); + border: 0; + border-radius: calc(2 * var(--universal-border-radius)); + background: var(--progress-back-color); + color: var(--progress-fore-color); } + progress::-webkit-progress-value { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress::-webkit-progress-bar { + background: var(--progress-back-color); } + progress::-moz-progress-bar { + background: var(--progress-fore-color); + border-top-left-radius: calc(2 * var(--universal-border-radius)); + border-bottom-left-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-webkit-progress-value { + border-radius: calc(2 * var(--universal-border-radius)); } + progress[value="1000"]::-moz-progress-bar { + border-radius: calc(2 * var(--universal-border-radius)); } + progress.inline { + display: inline-block; + vertical-align: middle; + width: 60%; } + +:root { + --spinner-back-color: #ddd; + --spinner-fore-color: #555; } + +@keyframes spinner-donut-anim { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } +.spinner { + display: inline-block; + margin: var(--universal-margin); + border: 0.25rem solid var(--spinner-back-color); + border-left: 0.25rem solid var(--spinner-fore-color); + border-radius: 50%; + width: 1.25rem; + height: 1.25rem; + animation: spinner-donut-anim 1.2s linear infinite; } + +/* + Custom elements for progress bars and spinners. +*/ +progress.primary { + --progress-fore-color: #1976d2; } + +progress.secondary { + --progress-fore-color: #d32f2f; } + +progress.tertiary { + --progress-fore-color: #308732; } + +.spinner.primary { + --spinner-fore-color: #1976d2; } + +.spinner.secondary { + --spinner-fore-color: #d32f2f; } + +.spinner.tertiary { + --spinner-fore-color: #308732; } + +/* + Definitions for icons - powered by Feather (https://feathericons.com/). +*/ +span[class^='icon-'] { + display: inline-block; + height: 1em; + width: 1em; + vertical-align: -0.125em; + background-size: contain; + margin: 0 calc(var(--universal-margin) / 4); } + span[class^='icon-'].secondary { + -webkit-filter: invert(25%); + filter: invert(25%); } + span[class^='icon-'].inverse { + -webkit-filter: invert(100%); + filter: invert(100%); } + +span.icon-alert { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12' y2='16'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-bookmark { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-calendar { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-credit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='4' width='22' height='16' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='1' y1='10' x2='23' y2='10'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-edit { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 14.66V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h5.34'%3E%3C/path%3E%3Cpolygon points='18 2 22 6 12 16 8 16 8 12 18 2'%3E%3C/polygon%3E%3C/svg%3E"); } +span.icon-link { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'%3E%3C/path%3E%3Cpolyline points='15 3 21 3 21 9'%3E%3C/polyline%3E%3Cline x1='10' y1='14' x2='21' y2='3'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-help { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='17' x2='12' y2='17'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-home { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z'%3E%3C/path%3E%3Cpolyline points='9 22 9 12 15 12 15 22'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-info { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='16' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='8' x2='12' y2='8'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-lock { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='11' width='18' height='11' rx='2' ry='2'%3E%3C/rect%3E%3Cpath d='M7 11V7a5 5 0 0 1 10 0v4'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-mail { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z'%3E%3C/path%3E%3Cpolyline points='22,6 12,13 2,6'%3E%3C/polyline%3E%3C/svg%3E"); } +span.icon-location { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z'%3E%3C/path%3E%3Ccircle cx='12' cy='10' r='3'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-phone { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-rss { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 11a9 9 0 0 1 9 9'%3E%3C/path%3E%3Cpath d='M4 4a16 16 0 0 1 16 16'%3E%3C/path%3E%3Ccircle cx='5' cy='19' r='1'%3E%3C/circle%3E%3C/svg%3E"); } +span.icon-search { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-settings { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3Cpath d='M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-share { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='18' cy='5' r='3'%3E%3C/circle%3E%3Ccircle cx='6' cy='12' r='3'%3E%3C/circle%3E%3Ccircle cx='18' cy='19' r='3'%3E%3C/circle%3E%3Cline x1='8.59' y1='13.51' x2='15.42' y2='17.49'%3E%3C/line%3E%3Cline x1='15.41' y1='6.51' x2='8.59' y2='10.49'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-cart { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='9' cy='21' r='1'%3E%3C/circle%3E%3Ccircle cx='20' cy='21' r='1'%3E%3C/circle%3E%3Cpath d='M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6'%3E%3C/path%3E%3C/svg%3E"); } +span.icon-upload { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'%3E%3C/path%3E%3Cpolyline points='17 8 12 3 7 8'%3E%3C/polyline%3E%3Cline x1='12' y1='3' x2='12' y2='15'%3E%3C/line%3E%3C/svg%3E"); } +span.icon-user { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23111' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'%3E%3C/path%3E%3Ccircle cx='12' cy='7' r='4'%3E%3C/circle%3E%3C/svg%3E"); } + +/* + Definitions for utilities and helper classes. +*/ +/* Utility module CSS variable definitions */ +:root { + --generic-border-color: rgba(0, 0, 0, 0.3); + --generic-box-shadow: 0 0.25rem 0.25rem 0 rgba(0, 0, 0, 0.125), 0 0.125rem 0.125rem -0.125rem rgba(0, 0, 0, 0.25); } + +.hidden { + display: none !important; } + +.visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } + +.bordered { + border: 0.0625rem solid var(--generic-border-color) !important; } + +.rounded { + border-radius: var(--universal-border-radius) !important; } + +.circular { + border-radius: 50% !important; } + +.shadowed { + box-shadow: var(--generic-box-shadow) !important; } + +.responsive-margin { + margin: calc(var(--universal-margin) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-margin { + margin: calc(var(--universal-margin) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-margin { + margin: var(--universal-margin) !important; } } + +.responsive-padding { + padding: calc(var(--universal-padding) / 4) !important; } + @media screen and (min-width: 500px) { + .responsive-padding { + padding: calc(var(--universal-padding) / 2) !important; } } + @media screen and (min-width: 1280px) { + .responsive-padding { + padding: var(--universal-padding) !important; } } + +@media screen and (max-width: 499px) { + .hidden-sm { + display: none !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .hidden-md { + display: none !important; } } +@media screen and (min-width: 1280px) { + .hidden-lg { + display: none !important; } } +@media screen and (max-width: 499px) { + .visually-hidden-sm { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 500px) and (max-width: 1279px) { + .visually-hidden-md { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } +@media screen and (min-width: 1280px) { + .visually-hidden-lg { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: -1px !important; + border: 0 !important; + padding: 0 !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(100%) !important; + clip-path: inset(100%) !important; + overflow: hidden !important; } } + +/*# sourceMappingURL=mini-default.css.map */ diff --git a/libs/STM32F4xx_HAL_Driver/_htmresc/st_logo.png b/libs/STM32F4xx_HAL_Driver/_htmresc/st_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8b80057fd3a454a97de1c9d732b7fede82c83227 GIT binary patch literal 18616 zcmbTd^-~<*6D~X~?jgaQV8LAj0X_tm1Ydk1xVy{Z3GPmS;IP2r4oh%%cMl#Qcz~Pl zz5l>lZ`GVRHB&V|boY7A^z(F|Z=Y4=aIwg-006*MkpHOuZ?5<^0x;12-SsK9!v0Mt zmQpHG08kT${nrHb-!rC@ysj$%ki7ceKq56ESOEZeJ%x`_nqEey{^(v>eK${gL>pJ% zX8+KBAR_W-jhDrs{egi|sP<73DP`UFoa(>xj;8qknEx2bL~2@t%3k>}hnl@CWQrW@ zqfK>@e3$sL-m%ftg0YAkk!@=P!Ognuz(zhb|Tux{FeX<<7(5oLVU8=W*sUZ*$TqlSb6o1O0a zzeP#ZW!;?#>0N5v?0D|q?mzD8-<^@1V0FH{fY}2A9ooXbylcB6Y>PVo4nMxLi|AWA z8M(b#9`j|%0v7ktATOSzsh-T7%Wqa>t*x!29M*iDetE6#^`?iEoQW5F*w7rjcWYw>-UyKyDHetK@Im)qdu0o-zudq@gQN3)r z=(%XIh|%7(Y}2mODA6--)=u;7mi|lUCki50L@QOyZN@2N`Bwwn9et)BF?yQr9`Sn# ze!a;09%cuNiCJ+Hwx|5Sw&L`0rJvq<$7D5j#Y=O^YcW)1x!+MVRWRVHrXDj~g@40Q zBvp_niE6-dasJKX&t@%;X`7_R9QhT$w_Dv~zW73kCM;9WC z#^@^R#^^HZ#`rQ5ZjC*^uYUMgw=ae5*IV2JyEL@LlJ1k!yA8p=fmyQ={`Pjq&sK}Y>k9r>*Y-3njDRLc8z*D?su--n+y(fpV8FB zwS%vLw=L>F9>rMJzXaXgg5NRvaHPKO=qdV`%ecKE^q=CNs6^=Vl)5QG9h0>AKM-1F zvU-S)!Vnz~yg}XNmnaKSqm&}<1}#nOBCWZsLvn3_pkm8Z)~*KF8yv=yRk*!4rf$7T zT*ey^g`%>`O82HoVNPMCaM^5e_Eeop`^`Wsro=Q9SzJ-{LW5j1QdRH>Oq5bEX({TJ-TNGPvNBrk5{my=8FEQ%0fftv4 z)$FK)-usf%cyd|Y@=r@u!~HI3-5_Q=E%R!AkEqtv$Yv%Zit4K`i*n5tM!wdwLFM?% z@N0D&tLS9%TD>`41R~`%HzXtZS6pjo$}fsAA6cq`&Llq^TE@#ID4eU}(xZH$-0oa>g$RMe)N_S(=w@nXEL&?{|e zd%-=H@Ei^9kz3up?3!?QYr2O7^M9)q_E2E@^vESGQ&5WzDh<(QgQEd3BICrRm8O)S!fPO#z(h0}Vk) zolMw(Ecl!UD7xMUH0>?+9qzTMCMQxcM+Od*!L7F!tiwSSG>D@|J~*c~gu?`RewztA z1cO8*h9GGR{``zPp9t6vZJ81Ar<-bz38Jv-ro`wI#Mq&-k$*5tL<>Pk=)T1H_z8YhPJDWCuq5c#f&iDRo3$~XHhc-#T3{whJvB?;N^IKpX^H#=oYNa@u&^9He20t za7qlYKRH^S(Tj2{XC=lPI|MVMOVVX4V8cbx(9Ix%YK__iyN9E(k)118*aO-OzZNT# zbhE^f=Cze>bdhX>8xBFW70+=Tb@QnIyKKmQGt`}ZHXrVVWgxIT1k&eFDonM5iFh{^ z;FtT_qYo%x6$`ChDD~;i`c>h@T~X~pZ&-v==wrV4)ra@?=39Z}7c)OR&&9#@9uxU( z?hh)jyY_o}tH;1B>v%95XoGM@gDYB{I@;aJAn;N$2z~uDX|IL`uf-*Mm1ic21|E8c zQZWw`gvb==bz|iv=774j$zii$vlW@T4LDFEfea$Z+frqVA{<)qP_mhp2AbFqEE(0z zfCJgi{n&vKxpSY#-W)(E-Y3u@1KQGcnWN=qz;Nz2-6>bIL8wZk?oy8xe49zo9Evpm zI>QVA&&4C5*aCjxksX%9lfPpQNw|#TzMQ;YvC%Rx=uA#dmU{e@tzaW&rq}9N5VXBw z6Mff^1He^5U}j4TZD};Z7u2!LZ@OjGIPgR|MLZ*9%)E@0nE%K=W5s+NOT~n_{fBc9 z8DlU6un9om`MN~!FtpPXkJSq(+KPHqF&N23_vGeqphc*cEAF=okHGoFWHHWTm&R zAZXR)=q}Jv`jsvKCoL27h?ylNq0fz5xasR{P`5RW_7kzL^b_#T@e?r5nGKuMX?!lz zcEq|hYJscWj{YtO1of8Xi0jH z6s+!rS0;ag(Cml~|NKB+tNwwq9kl+8wc0!T$L$CFw95drNPiuZ3jOf4G_NXoM$sQj zZn*2v3^ISC(OoqO%W>m};%SHDOcD)D7%f&?jnrI9&1_u;6m(x2g#=wb zH$Cl!I6f#QI6iFo2i^nPy^8_Rt0g@Gzv3FoK629)r#wPie#!P^T*B)9JDi>Qta-Ee zyLS}t0#vL+3WcNfUo47o=g+h7Q(waq$0Fo`#^t+!ugP{n=lV`j6a9^vBl)I!L&VaI zK(10FWw?KM*=_ynJ3HIwyD^##=aKUk4u|yIYk$&C>^B?x{I5c+Il`m3RQ%_=Tq`!D zQw3HQ7dw%VR~rkqeqr+THi``YT){njI8j~%3VNWBl3EUyQ zx>y&BaDTkwjg$12&1?kD`IcCB_?j~8XMfHm4iQ(TCj7-)DOn-+%UzP)ab?nnNlfTA zh(FmGsK1tl`G8>eb=1j~9lDZPh<*?zhjW@Gx5%UjcH4 zbrrd<#%%JyFrW`_Loz= zP30^V%kIB;=&%K@{YbXT6@(|c>dXlNk~?15SVEmMX6`Mjv>+MN2M$^N?ju|1T-qoW zJQV;x5rIpTc>eCM*`;fq^U3U2uW>l1RVxe^4B$CEub2J}+bN)$=(gE92((ah@ar_) z+I|k<9;iL6@Dyhc+LX|pTR>r3{P!==s^guY!a#cZ5Ry6QtTzvk zUh~+ICB=TnC(!+~G1}X`=zKbJF=VNy60Le=gO@j5lEJet5>jc!PbM+D!ZlS$KuYx&pkm{S?k)BU1<65@ z({=ySGqzCiV-vc5qOJ z48y)rR(Ys{uWIjyQX*o`4?xK$K9nE1K!t$coI~(ku$IzWaVM`ocnY1)=&_o_R%I_2 zZ_{Cs>@7#7ktZS)0EENs++_HHh39c*#7z#Pyifk3+e!lsET`nm%a#Zp{hflp4Vw$+ zOju*)#0tN99xzE1;G}_c;Oj@<_%Z8;SCB3P74uOYE__wpp<3HB0g0wsxZ1toEwg)5 z23F}NQwRV%3UQi)GQQt^$a%zzV8w>aIl;CkQ!6h%=n!jXPZ;sfULBWNTi1QT%V~R| zdrjBQt+%&EcrjOO0&pO(SR|R1%nis?Q}KUl75Q=`bI5TGenEMls+QNXGp;Grr-EZVy`f(ovFSmI(u6D90n zU}rWOG+9F)ioe9yO)lx~AD<~|_xP=uVs4I z6w+kccIU+(Ltf0bDM$mvJrBdPzjnQ4w#L-qTZ+S6V5l=pqj|%(!m@K!R(Sm5G<;5V zXK~r#d34;M-;>*+VXbyWbw`4vdOanA^uK`Ag&w)G;7}_OpATxWe^GjFe%&*Ocx)w7 zwt4Bs4luF3C-9V+n~E!?(W3d6$CtEn7OZ{~I`6iW|1x;QzkF49GF&d=Wg#fC2^Vn?KLfW@n~pFc4gBpg!U$uFR0 z6`f||PCJat3glNlwW|z^j;^p%9oQc82S&N+!L>xWR*UT~JbFCj)0}2J6c-rV3iVO! z`IdFp zB0H{SvHRu;zx(EM(0%j9fA`HVZ|@5Oo0EGok@w*1K*{Sg3QERYynQ|7kzI{t_?~>T zQGQ|?TPR(EZYAFen;>d7>k zc`O4jwao>J?dp~fG@8l|SBHzOE5h7?Ba_OYs%93|;KP${8}j%VGb?LRi<;yffk06& zmc)TH`g@-+zt@fG!z|MO3057>Y}ppB{w8IS2o68)NnHSA-jKa+X$k+&Klw{5Ksly#ye_HBKV&h1zbIsIT-|0XRq)zWf_~s9{=n3BOfpPy7{f5RZzL^9tdzjj zr)R?-SV}4UX;&dWNKq={6q|g;FEbIjXC}?$K%uY_ur_MF+MkJ>-c@8l1|6F7^BR4N zf%t(1oJ!m zg^z<^ddW{6+A~!=F*1he)s`5=HR&3O@tjq)pn!{ zodn}X=d$=iUh-ibxQ>PQw|#fHTLppRwXG}*HyUkLKB?Vxf>#@2_z&V#B0Cjvmfka$ znI~k?Pp)A)OXy(kdOeH7nbmp9bNb|>|e%T7Dg>BKo&y=JzU)v zs{+P#O$)wko3MOQY!bv_78@Q%uABK!ZPIi<~iCxyQ>J*D53j_;0vks;+?UxqO^ z8)9k;>&t3F)oFofc_t(0cdCn(OIM;4fePgKSw+PKcigoQR9JV_C-y`&%By+|aMjTd z;$iN6>#`KNXtG+yNhfl+PYn(#cr;Nf>DZ1mRU`A-PFI}Scq~0EgRR31c4LZcz_w!3 zU&-x*oGPQoz`-m#bYEC;V<7tHiC(wn395M}YNU9p|6@2$$6(9N_DyMjuOwT6X&Cu> zXg1{_^+%NsBhDf;)3V~J5%bl|^XVjqRgu^moR2288%NOgcLoNBkN6t5F&l2`tPvao zfAbQy!&*Ln*uWc{tVDqwT1{Q>{s19S6+;c@2e$2eZd>zL~I~M}G^8w4Y2bnyq)>=S+L6j%|@%XWqbYm%+}R z%Jg=|X7Y&0*lujN6>tzy)?{CBuT|FT#I=sU+569+)8oyIH?8?{Y{Im(PMHAGs5_GI z>1wLl+yiE$+I28-c2!jx)_?k2nIm}7iH=O{X#yL$s@}hUPf^xece9Vi{DUPRKm%@= zI4q=C$Qla?I0{;1W!^-Bt)o=r>#KNZnZPW3piq_&q`~HLF~1_^MHlt66*62}BJqzu zM;g!LlycVJ?1ohPMvFHu3^-`<`sR(iyLG`EB|;bk%3GG!#?x`m5gx zWnZm7bb@UTrR9OXVs1t)?(5a%Yqq>?ivrob2S7W|CH$C|Kscw z=5hgFRsHTTA{lDQ(a0VW8vk$By+wL4Ao<5{Br)oU$x2pMfJKrlPqr@4P$Y9Nt_7R| zCx>hhMeHtjM0mJ|?T<(EIY{^^cAiA&R=2C=g&o@6vm!E&&86BrLOf18fr==x77OBH zdyOvB1fjqxDMa5;G9@=qu?tN_vB?)=#H^qB;g*jHrr^*ISGt+pLXyWcu+bAWNk&IG zl?zGxV&+)tmQ@d~T5Yypa4*^P5t*t6C($W-Y9zknsGLXPPDR^RF~`>QcV4iB%ltJg#%JgzSOl!L!d<7;Gfa5FAv zjVdBTD(TpZ3>zF8@VbIAM{aYtDv8fh>oAmOoV`*>G_abe#aOPM+6b%!IzPP2K{>A5U*>>2+^+79)a z;+jQ03qhGCNA7Yx7^lX9Ba9FuFHNen`s{buqNeEv)$x#QoePK6M~soRL17NVafu`4RB%F$`Pl z5~X9X{(zDkw(=x-=6pOllhfSrJCozywriAokKZ^VZ?epc?F2YfOmC=V98gW?oL=*# zC!4VJtdyAXwE6cHlNoijVy3KiZxeTrjL5AO4?|IT4#6gV63bUTC!(fd*MK@3^J@F! zOg&Y}^l`KyT>$RnH8O17_%?_PVh?o(+5L|_R7c|c+R_PRXb26L8QM&z+5MaH{wtOk zn}L=^TXs*WwrBLOJ6hDKim{LKAa3?WEiRefh;#TMZ3y1zA%QAUYh={Ux!GU!o~ zQNH$+pUp$BPoB27%q zF^6BflF{;t=SZSz+GrMJ3q~ti7gQ;5SbjS`5!DFxQB8KOt1OQ(G%_V;vcdj>K_dXjNxb}0M?HyjDs(afDCVx%>+I2GAO;jMfy0Iwh$=Utfm z5snMAm4|C3O1?MDEQ%I@RL1I{SrN67(Q)b*7k&Ip+-THJr%-;ILx=v!SaW75@EH3` zUhVOn4CYZ>iZ!iaGNBq9Be`Mcq5Opf?{HZfcJM-VDr$qSCy^3Lij|O&UW{&ffZ&!( zaA9$H9_5lFs;vRx6|mmn{Ic~u%y*(_t~*m12^>%iUOQ9Ap<@`U;!iRpBZ5y=p}@B6 zSP;R6QS{hs7)q75Mgj7814d~Bae=<{A1Z5>;LN66N?m?;5pl?`*_wW1l4a8IBb4tyR6@^@^BOm`{tD6YyAv};)Te2G+K}4;<~T9 ztiHbWTlGjD1=omQ_viT9PJOR7GjZ^{`7u?a_$hGpx54G9Z4Uj-NJ+>3SA0ZSx1vXw zLxYWusP2Sm*#o~_#B)vb&lTfmtsonTnPHIvx!#}HYvp=bPcZe zcHOCWuo0{MxR+#P#Pz1PSlaT$g-HbB!hTlHpV_F!Ay^U-vb1-6W)!xh?3imeOv*Z3 z=D=Ij-4e>!J=_Q#nqT5Fkomgv(@3uQo!?=8R9Sw(0)&ni z2jsV8*xm^OAO91C)$^*!X=%ZHvh_G35URQ9mZ|{A0)E?gJcL0T$H-NA92s6VF$CYW z9RHBse3R!V%B}9#+)P1_9L@j@2VcH-GZ=N2{$k05r?kj$KxpvthW zd7m|F4Ka%sEOHJC`oN z{Q9h2$S$VYkMHBEw7ybMx&7`nIaMLI5n~s)u5f7_tg^|2p4eFF&|6C45|-}T zY2bbCicJ7u0b>nvzMSvbBTOChoOAKvC$b5)Y}lT;{a-@oZBJ!oQNfsC36M4qtjvVR zX;Qkn$Pw56!sOMyw2f6>a4-#^ zy$1D*lt}-KofQ^atUig?;uYP;un=4nq7RPpS6+7^7eT`a+9Hs&(5Wu`IyLv0kJINP zH{2$kHb`Me^3C!975F7KG!qcJ%Ot-tp1f*bJffu1KR9B1lQ=XYBq15?hlJ33*QN-~ z25i$#OI}x{k+-P3EKo3v2XVk4?t;KE4nj1dk!Zo@w6D?!o#k^~T|3?;an*{_dc}rZ zWWWrKbdBu0k$7Zn5A%~0$lei$vU1P?CE&!L*!t%`ziuxu= z$+Xt=qUvFYn;a&JSK-D!mWnDWtF|5q!R|hT$Hv!*O-Hv$ zFMd5*W#~$3AJN-2|IVd@2bWN6TIfD_0uz(~vS50vn&4k2seimRF5`Q+1IS}!NNHN| zuWuQz50#5kO>f(wTSg+{VKXLrOZR$Gm~DhS1f%%-9{FGG$s*ZrqKZL|g5VaRU11N3WB;tGWJx5jj1rPZ1}$YE7~gsu zE25FmauDeN0tjmI!T8LA_@Jktp-r4gQRI3~pz@ext*^u56U%RNNACtB2^N&i&Zkq_ z`%gV|mr`$f?Rog-De|tRlA$9w&gIG-7Zqk}`K~S#ez0!r0TA4$*?1vW^S1eRHim+x~x!Fuo?ZZGGykdj`C(v!pIX!M7^#v%t*g zcznI+6jSi4g8knZOJ2XD^*-Nu8++1xNL67@Dpa}id>w3=oC<2l|TauHqSGbyr z9Lb=M3fe$ymZM2IcIy2$WhWPLfA8YEy!~$2XHICgk})!EbwTa@re-=DC1|8#7fNFq6gJ2K}GKAX`f_@q32jY5x4yTSxUH;`}j*L?c8b@JA9D(4X1n>r5 zmjA{5zUzqX9?77@2f4TGSC#Gv z>RXD%m8Sx#GLz`?10nyLA3f`rKtm)2mp8 z2WUMD#ZK*6rx@tHUO&Z&$15&*p$9S&RarVs7nI?jWCTx!i z0n`(39&^Y>ScN)8+_K-B#JBi}jEM2qqgbCqWKx*4*ll_rs)9n)b|4=f&23 zGJ5Ub{5j_`P?1;gHXtz{3VvNPjI4v63M z7VR-O|JQRM-E&ZagmZ6Y#+`oTU{Zdpg*T>rA?e2lXyimlx-MsB_vpS!^2jDQhm%@q z{n8XwoaYQc8y7Itb%2)$a=$~0tev`)%-s+AXZ8I@XV4DuPx#4Z3^R?1Q&1e*!{+@j zwy0-{m|^s)xqlSU>jQk{owo@5+inF)-p_24DlAw`pUe~G8ATB<-h>G97|FK_kfkQlN-!Xir7CB=dF)cJj`)++W>CeZ z0KpG5Ul%&-7q_N%mRtvtM37+jS>A#7p`RadxDFCIFsAEA)28 zRc#)^^3Z1>`W_P8_n+_5l5pGfayTk_=7^k}d#ir!c>8mR4k$J+> z7$;sN^3k#e1A<-CaO6F6V7^1u(puc4hVnfPK2u$wSE_XF>^Bp?OAv{2Y8)b{(a(2LFQfe!w)T1x>k{ZpuhTF(Y6rhpZbrH!ElxM! z5seXw{2(-vFEyNn8P2QzldxYgR;$=9Va+n>oR-HQXL;u7|E|m|OuX!t) z=Y4P{a-kdSJHXaCvpi=8=DW$Bomevgq&Ys4T71MX_~k_QpcOJ7j|>5e z8fKax8KCNY#00?1+;-F_`mYl6?wiA0M9-%AWH7g{~~uALu>r1q7;w|*!aJIeE{mR8WtR@KBhs8TcC2jA=CW|Xy-ycIi>d)c7Okmo?_;IS6kWJ z(`FLRj~hxiQw>hGi`}`RB+q+jpRWZ9z114q7dyj#>yMG?n=NfcSz}CGOi5Bt#D4u( zFREX`PCs3=cqxne=H=$udT;=|-YI7ij;hPlH)3oXm z`Zikh-OIS^*V9YKw;%r4iW?YA#ppM%LKP=jnMYQ)JEBqy1t4U@E<8VwMW2U*KvaS5 zNDwVyHjTg6hvcbS>{N7lJu=~^Ut)S#sq~v9%#hIV2H~>o^9=!kEGypac0E4e6TQIW zr~+Bn`Sb4k*0*Zts;f;Vq@fsZn1hLBQyIO8W(13u0211vHK)RMC5neH4xx7?6jMVOl3i-ENH1NU{ z-FW1hXwfmWi;TOg`k_dSL1ckNlukjE5IiKg=2DaEcWG#qTCd+ts`vavz;Wye>fPE6 zy5Y~H#6~R#r29XgZcKEUWF`#TkPjT0Tb$nr`$rM*rO!0=z{AwY-%*%Y>1iy07;xo= zlqRRR7Oc25bnNStf}IG@3`}b^k0oTD!zg(19YJjRnXs}9jracK>Fw6_hgpNk9M$d_ zY;%@p@*94vn6~^S;rS|c_SBN9%41Y5CNDz~xgJ>zs5bOlC^*0Hm`3d+UdEAQlhAJ~ z9rS!JpiEjf-g5TxWc*_}=Uu;kRBG#hg)R{HVt_KfnWZwXW)vK%qN^F`Uk1yRWlJX^%Xv zrk4pFBKoY0c4V8}-7;k5jeHn#no6bE=CpUiQ*YjAXr&^e4Ji=kd5l#`F`6lq$7V{v z3HxGM@4$C!_rCJ0-}}J#b+>i@#M5T@ zDq!my3QKfc?}%tQt*O2KZN233YvPN6nJ}^KNmAv>Z%4u&!~ecZRVXA}Vl6Juc1QC% z^+u0V1RbM%wwc6J;|v%G|8k{t}#XaV3b2aS>;{E0?a{QN?D zjap1}Foj*+4gOfLe03+j+-fGX6EVmh%q%{kCs18^=Y$ttM`Ru~Sih(@mxvo*(|OHJwq(zE2(ex%#gkzo*Y14gL&0 zb&R`Soa5K^wB%jo6cc>zQGL@J1IWOVy&G6nrZ5tClv8t|5cv^+Gb2^+T0kC3kdVb= zzt>d9Y8%qhJjVP{A;^*2E;@stxE=CCM8#hlN3jEzVQ}z~l*fFX-3jF?-%dnrKMp>* z+*ojsjy{>@Jvb5ZmHokSc4fmUNZRBEvkDd^(WV&AoGicLZM&xx+F?MzT8H=FtNK9| zS}XSejv}P(R*P5=IL)L^{d8bx{SC>9DDxXj4@z-n^Hya-p}k%LC>kvh2A}eK-{n8P z{ymeI^r5$}WuJ`hTT7y&m(wGugFoqC45jML$-|3L7JDo`mbG@4AeOa9^F5Xfc~AdJ z6z*HExRMYeE;qZsGE(eCPFCa$fMk$Uzn)5Lqpt$(K3(+J)whl&sJ0{&+hDO7rV zmH=Vx#~{t)BZI;GL9NP4eoCJAPi}V8s2_pM0^Qn!dLjeT+!j52$p%MSaS9-1=VIXE zZZI?CV3-Z~UNNk|?P_bEXiaFvcS$(=j(imNA_Txz*qk*3Zt> zNTsgN3vU6G(NEuWibkSSE-gZ&wr@}`tuvHEIJGFQY)vT7_Sn%Zf>;noCdR{II*9Uy zi1DPT!QZt9edc?XCO_%vF)Vha6tK-jiPV+wdZr2-8Z+moIE4fA9Um2wrmprd`ujDw zA4$!<#8*6C%(UP!wX!r@9XeCS{UX~rhBT6- z&m5@`REID~K)qRRLN40)>Fz=?P=C-jXZA1}lMo#Lic@|(zYtC?Sr$}gjz;wX-)dH; z>kQvsjFQ|FEvL5r4GE`Vi>HJ+qxMkQH`jx)M#C81t{fBmVaUEu2p_>}$^Lp*OiKYZg_C_ycw2+?0OT`)la$oyQwx zn_edD@HInp4-Gny;i{I~SnCp_RpFSS_!Eo_CI3DYHotlBCu`)~d17BV58M;K#oqAY zMpX+Xw9;xj#wpOozs(lT<+Th^5&14m(|Q*%;z`vKh4SNgAVBe}N~g2sLPrFC2|fE< zFpnnM-xp>{8@7DssTYKd@0S%KXilVkqrjiHGyiM<4X=4ToUoPe$O?bRyn$W!y*w+D z6&Dp2t9Ct*jrJO53Vv$UzniUP=-;pr=_NhmXKlFLRkmbSfW7QwHhvWb87Y|_ zx8ovSSXKm9h{zGnW$Hh-iI?ZMHSbjn*3Sh{-$#hX$;rQovTb9bL)q_$Wc zZmKiDhCM5p5vXSn($(MVPz`Tl^8Dq9O!MXzxdIh}Yi;I?zh>o(TXxwNlF}fbbJWC- z#GcWxTx796z)2UUjk&XWZFb3^oh-r)7Kkx{urkexT2D1!HLjPN~zvz2X#hz4#kSWLV*CW#DJu#do;exLU5E*Yb2H*HhXE&}5w)`L0O>xl{F?nRCT2 z*sv_q70&aZdR}eGSdA;#MccWyIlME%-v<$!Uv*^qnA&%(krwShZthK$iyit6H#l;> zK-^@!-w;mtEMfj7rnxx}?MKV=JHn^z-cHiGPN(d-mV0j(9hnwwg#l4%su_AWn&D=e zjR-cx9)55a@TwJcUi!8R@A2vD&T99g^diZcn-!n?8)u3269>8(cQRcMciiUGO^eip z5B)0E8kXbcz#sx*&|^TUl$Lb)lb&Ip>#TdtDfUcwzE~nzmuQ7EmTjAgdgUiGuSuNa zpCb6rE6(O5o(^pW-+RuE)g@nrZK=PFeQcL58r8o>9J$FQ<9+2A1d*DBdQ!b*dT;;4 z$Xo4EWN=S2^E$tAy9hSL=6Vn#bHD2g;0=sNhjJ6d)KUocZ)+A6o6_A*qTK}$*h#RS zyk#XkuOO@^1ht8v-%9N{Y9oewzu$e7L(scb^mXW2_TiW*-y)vNyH`OadIrI^Y>*Zd zp?=ROXFoq0Kk^tpwCFt$B)QKsZPM$&nJ*fs2;Xd)FtPd@FMUTnfVUp;sJHFaw;TuBTKR%BOW_}ClL_Bhz{A0l{Qgc%@tjIWj2ys8T z-56z(;=%E*LE!6!#2)6$>Eq4>1p;7`)Z_NSc1X=l%@0`gB7usIOR#p2{Cap%H#@u+ z`w+GL;VMer0DCjGMC|TGF_;&EgwZvSq=Q8@4}X7rF+n51h%CM@hl5WX$J z1a?I~km{+qh|RA-3+BNxgHjmg>KA!Bo!rA$QbB?cckI}KdkcLRox3JZd`fkXjx#A+ z_&En<1xc&Qmnoz0c*OV_guW?$J#uUHP(jS@beks0sZ#) z21ebzv6U?Wp@^S4Wn-$u_zmK3cE*C1Mlc5xAi|J_lu9>vY@H z+=VfBpk=&5g2V=pY;m2PHSN1`4hDAzs43VInEYm~-~S`AxRI%f?TU84wXtx z=s<1xk#OUIW)~ZG_2?E}ncAz?RlZ%Nu{wqJtc71aL~G>$Y^@Cl^I zh)|w&6EwGxERMm32{6|adN{lmCnO=?!|jUP3Ws1;e!SWGzjeq)Lvs!ZTTq&ie5vo- z`1p%Yqwt8KsRfc+Zbj`#L-1}(Bwi~Ax5qO&ZU@{ejQ+Hp4mt4VPoV_VeCr(6zF z9UR1ae&+2iX+s6E2V}Lxc6ZM+-8S6$a@?&Cn^C~=sPX~d#JLm;5Qw1n%IW*&PBV?q z09O(5{}gEc5xG_jOowcjF=x4y(&YamY5r}Y`?S#80Bh&J&-}>XgL{roRVEZo{x*i~ ziq&;TCj2%^Ju@%&4lTnyhe)5-5PDrQb*+9kAHW!EOaiu61g8cl_=CS1bA@HjhP}H5 zEBJUSKy2WF;ua_T{{-d-8TdvHidCA`BXq&j4cFtL z^yXVy20#nD1@%y@Y5U4sF1MvXa8K;F7B|Z;gH>tspveGY5S|}@U_A#|Imi?6GS1f%=ROP|BEkV#WqVG3b_;n2 z;H#;^adfh%ovD>w5Gs4>tI$7iJW3x%2mWus`fl%IFZf2qhN?JgWZYM_WBdsAyZ9Ln zRkEUt($@b`?c4fgl`7mn2lzu)}t zF)QPs=rMRr?Dp9+=yMv@`)?NKswHtVMS+34S>A@W)D9NFirDEhF)P8UhG0LzO-*O0 zw~iYtAHX;-bhAs~r#R<26~a<=Te-BB1z_}yavF7s_X>@Au~8kI-fv?*ch&2-MEDeRpn$| zQs#J6{sP}E#c@zKLH{=n*1NNgxp^;34)cyq+y$_nMaXHdPefdQB&ZYuaBF&F+#jI) z5iI(HZ*=0~V#^Xg^oqt{LGBS3`Mzzz-b6=qrl1#6B|u? z)MRjg9LIM9!?@uFajP;=#Ssg@2~wUs91pUhTWF1+X;!z;#!7zZ!HA3(S&VVh0-H-7)D5Ez?jhb5*13LRK%!y+ z0JbakM=Tfr@d$}P-7SM{#QqrU2pOeg#laPR_u*ECoxGxwD+5qp7mJFAC4KD`kx<@y z!H-TwF(`nXfja!2zxynS|Kfw?Nv{=+iYwx~iR_4 zsDFPJT72Tn&;L~mWIpqIHR?q6{H5=03xogjIQ00LT=Sm?Yu??dTo^X%GTU3y3 z5U%wt^lQ~lI;@oqpCR=JSG?o&&sGC)JkTBL$iPQn)gVhj=u1Ww=)nAbnfA|CTF1W} zHDFT%X57(fTIQ+HQ=ZLM-4b?z)=H^8gSHr jqXrx`;HZHtT?79Qd=?ufS>7*000000NkvXXu0mjfyH5ns literal 0 HcmV?d00001 diff --git a/libs/hal/Makefile b/libs/hal/Makefile deleted file mode 100644 index 7737d40..0000000 --- a/libs/hal/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../../Makefile.conf - -TARGET=libhal.a - -# Includes -CFLAGS+= -I. -CFLAGS+= -I../cmsis - - -SRC=$(wildcard *.c) -OBJ=$(subst .c,.o,$(SRC)) -DEPENDS=$(subst .c,.d,$(SRC)) - -.PHONY: all clean - -all: $(TARGET) - -$(TARGET): $(OBJ) - $(AR) -cr $@ $^ - -%.o: %.c - $(CC) $(CFLAGS) -o $@ -c $^ - -clean: - mv $(OBJ) /tmp/ - mv $(TARGET) /tmp/ diff --git a/libs/st_usb/Makefile b/libs/st_usb/Makefile index 4117567..2611a7b 100644 --- a/libs/st_usb/Makefile +++ b/libs/st_usb/Makefile @@ -5,11 +5,12 @@ TARGET=libst_usb.a # Includes CFLAGS+= -I. CFLAGS+= -I../cmsis -CFLAGS+= -I../hal +CFLAGS+= -I../STM32F4xx_HAL_Driver/Inc -SRC=$(wildcard *.c) -OBJ=$(subst .c,.o,$(SRC)) -DEPENDS=$(subst .c,.d,$(SRC)) +C_SRC=$(wildcard *.c) +C_OBJ=$(subst .c,.o,$(C_SRC)) + +OBJ=$(C_OBJ) .PHONY: all clean @@ -22,5 +23,5 @@ $(TARGET): $(OBJ) $(CC) $(CFLAGS) -o $@ -c $^ clean: - mv $(OBJ) /tmp/ - mv $(TARGET) /tmp/ + rm -vf $(OBJ) + rm -vf $(TARGET) diff --git a/src/Makefile b/src/Makefile index 53c0619..12f420a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ TARGET_BIN=$(TARGET).bin # Includes INC+= -I../libs/cmsis -INC+= -I../libs/hal +INC+= -I../libs/STM32F4xx_HAL_Driver/Inc INC+= -I../libs/st_usb CFLAGS+=$(INC) @@ -15,7 +15,7 @@ CXXFLAGS+=$(INC) # lib objects LIB_OBJ+=$(wildcard ../libs/cmsis/*.o) -LIB_OBJ+=$(wildcard ../libs/hal/*.o) +LIB_OBJ+=$(wildcard ../libs/STM32F4xx_HAL_Driver/Src/*.o) LIB_OBJ+=$(wildcard ../libs/st_usb/*.o) C_SRC=$(wildcard *.c) @@ -45,7 +45,7 @@ $(TARGET_ELF): $(OBJ) $(LD) $(CXXFLAGS) $(LDFLAGS) $(OBJ) $(LIB_OBJ) -o $(TARGET_ELF) clean: - mv $(OBJ) /tmp/ - mv $(TARGET_ELF) /tmp/ - mv $(TARGET_HEX) /tmp/ - mv $(TARGET_BIN) /tmp/ + rm -vf $(OBJ) + rm -vf $(TARGET_ELF) + rm -vf $(TARGET_HEX) + rm -vf $(TARGET_BIN)